agora inbox for [email protected]help / color / mirror / Atom feed
[PATCH v24 09/15] Add regression tests for Incremental View Maintenance 78+ messages / 3 participants [nested] [flat]
* [PATCH v28 10/11] Add regression tests for Incremental View Maintenance @ 2021-03-10 02:11 Takuma Hoshiai <[email protected]> 0 siblings, 0 replies; 78+ messages in thread From: Takuma Hoshiai @ 2021-03-10 02:11 UTC (permalink / raw) --- src/bin/pg_dump/pg_dump.h | 1 + .../regress/expected/incremental_matview.out | 1031 +++++++++++++++++ src/test/regress/parallel_schedule | 2 +- src/test/regress/sql/incremental_matview.sql | 534 +++++++++ 4 files changed, 1567 insertions(+), 1 deletion(-) create mode 100644 src/test/regress/expected/incremental_matview.out create mode 100644 src/test/regress/sql/incremental_matview.sql diff --git a/src/bin/pg_dump/pg_dump.h b/src/bin/pg_dump/pg_dump.h index 119293a751..c3960a4192 100644 --- a/src/bin/pg_dump/pg_dump.h +++ b/src/bin/pg_dump/pg_dump.h @@ -322,6 +322,7 @@ typedef struct _tableInfo int numParents; /* number of (immediate) parent tables */ struct _tableInfo **parents; /* TableInfos of immediate parents */ + bool isivm; /* is incrementally maintainable materialized view? */ /* diff --git a/src/test/regress/expected/incremental_matview.out b/src/test/regress/expected/incremental_matview.out new file mode 100644 index 0000000000..b1e9424508 --- /dev/null +++ b/src/test/regress/expected/incremental_matview.out @@ -0,0 +1,1031 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (i int, j int); +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +CREATE TABLE mv_base_b (i int, k int); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ERROR: materialized view "mv_ivm_1" has not been populated +HINT: Use the REFRESH MATERIALIZED VIEW command. +REFRESH MATERIALIZED VIEW mv_ivm_1; +NOTICE: could not create an index on materialized view "mv_ivm_1" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 17 +(1 row) + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 1 +(1 row) + +ROLLBACK; +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_rename_index" on materialized view "mv_ivm_rename" +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +ERROR: IVM column can not be renamed +DROP MATERIALIZED VIEW mv_ivm_rename; +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_unique_index" on materialized view "mv_ivm_unique" +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +ERROR: unique index creation on IVM columns is not supported +DROP MATERIALIZED VIEW mv_ivm_unique; +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +NOTICE: could not create an index on materialized view "mv_ivm_func" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +NOTICE: could not create an index on materialized view "mv_ivm_no_tbl" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_duplicate" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +NOTICE: created index "mv_ivm_distinct_index" on materialized view "mv_ivm_distinct" +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 20 + 30 + 40 + 50 +(6 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +ROLLBACK; +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 120 | 2 | 60.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+---------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 220 | 2 | 110.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 20 | 1 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 120 | 2 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; + sum | count +-----+------- +(0 rows) + +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; + i | sum | count +---+-----+------- +(0 rows) + +ROLLBACK; +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 150 | 5 | 30.0000000000000000 +(1 row) + +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 210 | 6 | 35.0000000000000000 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +NOTICE: created index "mv_ivm_avg_bug_index" on materialized view "mv_ivm_avg_bug" +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 3 | 3.3333333333333333 + 2 | 80 | 3 | 26.6666666666666667 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_min_max_index" on materialized view "mv_ivm_min_max" +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 10 + 2 | 20 | 20 + 3 | 30 | 30 + 4 | 40 | 40 + 5 | 50 | 50 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 12 + 2 | 20 | 22 + 3 | 30 | 32 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 11 | 12 + 2 | 20 | 22 + 3 | 30 | 31 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min_max" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 50 +(1 row) + +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 0 | 70 +(1 row) + +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 60 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + | +(1 row) + +ROLLBACK; +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min; + min +----- + 10 +(1 row) + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + min +----- + 20 +(1 row) + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; + min +----- + 30 +(1 row) + +ROLLBACK; +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | sum +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | b +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ERROR: too many column names were specified +ROLLBACK; +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +NOTICE: could not create an index on materialized view "mv_self" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +----+---- + 10 | 10 + 20 | 20 + 30 | 30 +(3 rows) + +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 30 | 30 + 40 | 40 + 200 | 200 +(3 rows) + +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 130 | 130 + 300 | 300 +(4 rows) + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 70 | 70 + 70 | 77 + 77 | 70 + 77 | 77 + 130 | 130 + 300 | 300 +(8 rows) + +ROLLBACK; +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY v1; + v1 | v2 +----+----- + 10 | 100 + 20 | 200 + 30 | 300 +(3 rows) + +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv ORDER BY v1; + v1 | v2 +------+----- + 10 | 100 + 11 | 100 + 1020 | 200 + 1020 | 222 +(4 rows) + +ROLLBACK; +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +NOTICE: created index "mv_ri_index" on materialized view "mv_ri" +SELECT * FROM mv_ri ORDER BY i1; + i1 | i2 +----+---- + 1 | 1 + 2 | 2 + 3 | 3 +(3 rows) + +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; + i1 | i2 +----+---- + 3 | 3 + 10 | 10 +(2 rows) + +ROLLBACK; +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | +(2 rows) + +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | 20 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i +--- +(0 rows) + +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; + i +--- + 1 + +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 30 + | 3 +(2 rows) + +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 300 + | 30 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 1 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 4 +(1 row) + +ROLLBACK; +-- IMMV containing user defined type +BEGIN; +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: return type mytype is only a shell +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: argument type mytype is only a shell +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +NOTICE: could not create an index on materialized view "mv_mytype" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + x +--- + 1 +(1 row) + +ROLLBACK; +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +ERROR: OUTER JOIN is not supported on incrementally maintainable materialized view +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +ERROR: CTE is not supported on incrementally maintainable materialized view +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +ERROR: ORDER BY clause is not supported on incrementally maintainable materialized view +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; +ERROR: HAVING clause is not supported on incrementally maintainable materialized view +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; +ERROR: mutable function is not supported on incrementally maintainable materialized view +HINT: functions must be marked IMMUTABLE +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; +ERROR: LIMIT/OFFSET clause is not supported on incrementally maintainable materialized view +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; +ERROR: DISTINCT ON is not supported on incrementally maintainable materialized view +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); +ERROR: TABLESAMPLE clause is not supported on incrementally maintainable materialized view +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; +ERROR: window functions are not supported on incrementally maintainable materialized view +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +ERROR: aggregate function with FILTER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +ERROR: aggregate function with DISTINCT arguments is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +ERROR: aggregate function with ORDER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); +ERROR: GROUPING SETS, ROLLUP, or CUBE clauses is not supported on incrementally maintainable materialized view +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ERROR: inheritance parent is not supported on incrementally maintainable materialized view +ROLLBACK; +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; +ERROR: UNION/INTERSECT/EXCEPT statements are not supported on incrementally maintainable materialized view +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; +ERROR: empty target list is not supported on incrementally maintainable materialized view +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; +ERROR: FOR UPDATE/SHARE clause is not supported on incrementally maintainable materialized view +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; +ERROR: column name __ivm_count__ is not supported on incrementally maintainable materialized view +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; +ERROR: GROUP BY expression not appearing in select list is not supported on incrementally maintainable materialized view +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); +ERROR: VALUES is not supported on incrementally maintainable materialized view +-- views containing base tables with Row Level Security +DROP USER IF EXISTS ivm_admin; +NOTICE: role "ivm_admin" does not exist, skipping +DROP USER IF EXISTS ivm_user; +NOTICE: role "ivm_user" does not exist, skipping +CREATE USER ivm_admin; +CREATE USER ivm_user; +--- create a table with RLS +SET SESSION AUTHORIZATION ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; +--- create a view owned by ivm_user +SET SESSION AUTHORIZATION ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +NOTICE: could not create an index on materialized view "ivm_rls" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+---------- + 1 | foo | ivm_user +(1 row) + +RESET SESSION AUTHORIZATION; +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+---------- + 1 | foo | ivm_user + 3 | baz | ivm_user +(2 rows) + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'ivm_user' WHERE id = 2) +SELECT; +-- +(1 row) + +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+-------+---------- + 2 | bar | ivm_user + 3 | baz | ivm_user + 6 | corge | ivm_user +(3 rows) + +--- +SET SESSION AUTHORIZATION ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +NOTICE: could not create an index on materialized view "ivm_rls2" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +RESET SESSION AUTHORIZATION; +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +-- +(1 row) + +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + id | data | owner | num +----+-------+----------+--------- + 2 | bar | ivm_user | two + 3 | baz_2 | ivm_user | three_2 + 6 | corge | ivm_user | six +(3 rows) + +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; +NOTICE: created index "mv_idx1_index" on materialized view "mv_idx1" +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; +NOTICE: created index "mv_idx2_index" on materialized view "mv_idx2" +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; +NOTICE: created index "mv_idx3_index" on materialized view "mv_idx3" +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +NOTICE: could not create an index on materialized view "mv_idx4" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; +NOTICE: could not create an index on materialized view "mv_idx5" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +-- cleanup +DROP TABLE rls_tbl CASCADE; +NOTICE: drop cascades to 2 other objects +DETAIL: drop cascades to materialized view ivm_rls +drop cascades to materialized view ivm_rls2 +DROP TABLE num_tbl CASCADE; +DROP USER ivm_user; +DROP USER ivm_admin; +DROP TABLE mv_base_b CASCADE; +NOTICE: drop cascades to 3 other objects +DETAIL: drop cascades to materialized view mv_ivm_1 +drop cascades to view b_view +drop cascades to materialized view b_mview +DROP TABLE mv_base_a CASCADE; diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index cf46fa3359..013f5db7fb 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -78,7 +78,7 @@ test: brin_bloom brin_multi # psql depends on create_am # amutils depends on geometry, create_index_spgist, hash_index, brin # ---------- -test: create_table_like alter_generic alter_operator misc async dbsize merge misc_functions sysviews tsrf tid tidscan tidrangescan collate.icu.utf8 incremental_sort create_role +test: create_table_like alter_generic alter_operator misc async dbsize merge misc_functions sysviews tsrf tid tidscan tidrangescan collate.icu.utf8 incremental_sort create_role incremental_matview # collate.*.utf8 tests cannot be run in parallel with each other test: rules psql psql_crosstab amutils stats_ext collate.linux.utf8 collate.windows.win1252 diff --git a/src/test/regress/sql/incremental_matview.sql b/src/test/regress/sql/incremental_matview.sql new file mode 100644 index 0000000000..63e26da767 --- /dev/null +++ b/src/test/regress/sql/incremental_matview.sql @@ -0,0 +1,534 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (i int, j int); +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +CREATE TABLE mv_base_b (i int, k int); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); + +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +REFRESH MATERIALIZED VIEW mv_ivm_1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; + +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; +ROLLBACK; + +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +DROP MATERIALIZED VIEW mv_ivm_rename; + +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +DROP MATERIALIZED VIEW mv_ivm_unique; + +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +ROLLBACK; + +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +ROLLBACK; + +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +ROLLBACK; + +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +ROLLBACK; + +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +ROLLBACK; + +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min; + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); + +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; +ROLLBACK; + +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +SELECT * FROM mv_self ORDER BY v1; +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; +SELECT * FROM mv_self ORDER BY v1; + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + +ROLLBACK; + +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +SELECT * FROM mv ORDER BY v1; +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; +SELECT * FROM mv ORDER BY v1; +ROLLBACK; + +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +SELECT * FROM mv_ri ORDER BY i1; +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; +ROLLBACK; + +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +-- IMMV containing user defined type +BEGIN; + +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); + +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; + +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); + +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); + +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + +ROLLBACK; + +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; + +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; + +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; + +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; + +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; + +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); + +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; + +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); + +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ROLLBACK; + +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; + +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; + +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; + +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; + +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; + +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; + +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); + +-- views containing base tables with Row Level Security +DROP USER IF EXISTS ivm_admin; +DROP USER IF EXISTS ivm_user; +CREATE USER ivm_admin; +CREATE USER ivm_user; + +--- create a table with RLS +SET SESSION AUTHORIZATION ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); + +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; + +--- create a view owned by ivm_user +SET SESSION AUTHORIZATION ivm_user; + +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; +RESET SESSION AUTHORIZATION; + +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'ivm_user' WHERE id = 2) +SELECT; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- +SET SESSION AUTHORIZATION ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +RESET SESSION AUTHORIZATION; + +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); + +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; + +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; + +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; + +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; + +-- cleanup + +DROP TABLE rls_tbl CASCADE; +DROP TABLE num_tbl CASCADE; +DROP USER ivm_user; +DROP USER ivm_admin; + +DROP TABLE mv_base_b CASCADE; +DROP TABLE mv_base_a CASCADE; -- 2.25.1 --Multipart=_Thu__1_Jun_2023_23_59_09_+0900_/G5+8nG46.f1T42K Content-Type: text/x-diff; name="v28-0011-Add-documentations-about-Incremental-View-Mainte.patch" Content-Disposition: attachment; filename="v28-0011-Add-documentations-about-Incremental-View-Mainte.patch" Content-Transfer-Encoding: 7bit ^ permalink raw reply [nested|flat] 78+ messages in thread
* [PATCH v31 10/11] Add regression tests for Incremental View Maintenance @ 2021-03-10 02:11 Takuma Hoshiai <[email protected]> 0 siblings, 0 replies; 78+ messages in thread From: Takuma Hoshiai @ 2021-03-10 02:11 UTC (permalink / raw) --- .../regress/expected/incremental_matview.out | 1030 +++++++++++++++++ src/test/regress/parallel_schedule | 2 +- src/test/regress/sql/incremental_matview.sql | 533 +++++++++ 3 files changed, 1564 insertions(+), 1 deletion(-) create mode 100644 src/test/regress/expected/incremental_matview.out create mode 100644 src/test/regress/sql/incremental_matview.sql diff --git a/src/test/regress/expected/incremental_matview.out b/src/test/regress/expected/incremental_matview.out new file mode 100644 index 0000000000..8946d09f5d --- /dev/null +++ b/src/test/regress/expected/incremental_matview.out @@ -0,0 +1,1030 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (i int, j int); +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +CREATE TABLE mv_base_b (i int, k int); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ERROR: materialized view "mv_ivm_1" has not been populated +HINT: Use the REFRESH MATERIALIZED VIEW command. +REFRESH MATERIALIZED VIEW mv_ivm_1; +NOTICE: could not create an index on materialized view "mv_ivm_1" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 17 +(1 row) + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 1 +(1 row) + +ROLLBACK; +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_rename_index" on materialized view "mv_ivm_rename" +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +ERROR: IVM column can not be renamed +DROP MATERIALIZED VIEW mv_ivm_rename; +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_unique_index" on materialized view "mv_ivm_unique" +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +ERROR: unique index creation on IVM columns is not supported +DROP MATERIALIZED VIEW mv_ivm_unique; +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +NOTICE: could not create an index on materialized view "mv_ivm_func" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +NOTICE: could not create an index on materialized view "mv_ivm_no_tbl" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_duplicate" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +NOTICE: created index "mv_ivm_distinct_index" on materialized view "mv_ivm_distinct" +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 20 + 30 + 40 + 50 +(6 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +ROLLBACK; +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 120 | 2 | 60.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+---------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 220 | 2 | 110.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 20 | 1 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 120 | 2 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; + sum | count +-----+------- +(0 rows) + +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; + i | sum | count +---+-----+------- +(0 rows) + +ROLLBACK; +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 150 | 5 | 30.0000000000000000 +(1 row) + +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 210 | 6 | 35.0000000000000000 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +NOTICE: created index "mv_ivm_avg_bug_index" on materialized view "mv_ivm_avg_bug" +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 3 | 3.3333333333333333 + 2 | 80 | 3 | 26.6666666666666667 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_min_max_index" on materialized view "mv_ivm_min_max" +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 10 + 2 | 20 | 20 + 3 | 30 | 30 + 4 | 40 | 40 + 5 | 50 | 50 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 12 + 2 | 20 | 22 + 3 | 30 | 32 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 11 | 12 + 2 | 20 | 22 + 3 | 30 | 31 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min_max" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 50 +(1 row) + +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 0 | 70 +(1 row) + +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 60 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + | +(1 row) + +ROLLBACK; +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min; + min +----- + 10 +(1 row) + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + min +----- + 20 +(1 row) + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; + min +----- + 30 +(1 row) + +ROLLBACK; +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | sum +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | b +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ERROR: too many column names were specified +ROLLBACK; +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +NOTICE: could not create an index on materialized view "mv_self" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +----+---- + 10 | 10 + 20 | 20 + 30 | 30 +(3 rows) + +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 30 | 30 + 40 | 40 + 200 | 200 +(3 rows) + +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 130 | 130 + 300 | 300 +(4 rows) + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 70 | 70 + 70 | 77 + 77 | 70 + 77 | 77 + 130 | 130 + 300 | 300 +(8 rows) + +ROLLBACK; +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY v1; + v1 | v2 +----+----- + 10 | 100 + 20 | 200 + 30 | 300 +(3 rows) + +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv ORDER BY v1; + v1 | v2 +------+----- + 10 | 100 + 11 | 100 + 1020 | 200 + 1020 | 222 +(4 rows) + +ROLLBACK; +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +NOTICE: created index "mv_ri_index" on materialized view "mv_ri" +SELECT * FROM mv_ri ORDER BY i1; + i1 | i2 +----+---- + 1 | 1 + 2 | 2 + 3 | 3 +(3 rows) + +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; + i1 | i2 +----+---- + 3 | 3 + 10 | 10 +(2 rows) + +ROLLBACK; +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | +(2 rows) + +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | 20 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i +--- +(0 rows) + +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; + i +--- + 1 + +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 30 + | 3 +(2 rows) + +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 300 + | 30 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 1 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 4 +(1 row) + +ROLLBACK; +-- IMMV containing user defined type +BEGIN; +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: return type mytype is only a shell +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: argument type mytype is only a shell +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +NOTICE: could not create an index on materialized view "mv_mytype" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + x +--- + 1 +(1 row) + +ROLLBACK; +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +ERROR: OUTER JOIN is not supported on incrementally maintainable materialized view +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +ERROR: CTE is not supported on incrementally maintainable materialized view +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +ERROR: ORDER BY clause is not supported on incrementally maintainable materialized view +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; +ERROR: HAVING clause is not supported on incrementally maintainable materialized view +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; +ERROR: mutable function is not supported on incrementally maintainable materialized view +HINT: functions must be marked IMMUTABLE +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; +ERROR: LIMIT/OFFSET clause is not supported on incrementally maintainable materialized view +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; +ERROR: DISTINCT ON is not supported on incrementally maintainable materialized view +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); +ERROR: TABLESAMPLE clause is not supported on incrementally maintainable materialized view +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; +ERROR: window functions are not supported on incrementally maintainable materialized view +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +ERROR: aggregate function with FILTER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +ERROR: aggregate function with DISTINCT arguments is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +ERROR: aggregate function with ORDER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); +ERROR: GROUPING SETS, ROLLUP, or CUBE clauses is not supported on incrementally maintainable materialized view +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ERROR: inheritance parent is not supported on incrementally maintainable materialized view +ROLLBACK; +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; +ERROR: UNION/INTERSECT/EXCEPT statements are not supported on incrementally maintainable materialized view +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; +ERROR: empty target list is not supported on incrementally maintainable materialized view +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; +ERROR: FOR UPDATE/SHARE clause is not supported on incrementally maintainable materialized view +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; +ERROR: column name __ivm_count__ is not supported on incrementally maintainable materialized view +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; +ERROR: GROUP BY expression not appearing in select list is not supported on incrementally maintainable materialized view +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); +ERROR: VALUES is not supported on incrementally maintainable materialized view +-- views containing base tables with Row Level Security +DROP USER IF EXISTS ivm_admin; +NOTICE: role "ivm_admin" does not exist, skipping +DROP USER IF EXISTS ivm_user; +NOTICE: role "ivm_user" does not exist, skipping +CREATE USER ivm_admin; +CREATE USER ivm_user; +--- create a table with RLS +SET SESSION AUTHORIZATION ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; +--- create a view owned by ivm_user +SET SESSION AUTHORIZATION ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +NOTICE: could not create an index on materialized view "ivm_rls" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+---------- + 1 | foo | ivm_user +(1 row) + +RESET SESSION AUTHORIZATION; +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+---------- + 1 | foo | ivm_user + 3 | baz | ivm_user +(2 rows) + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'ivm_user' WHERE id = 2) +SELECT; +-- +(1 row) + +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+-------+---------- + 2 | bar | ivm_user + 3 | baz | ivm_user + 6 | corge | ivm_user +(3 rows) + +--- +SET SESSION AUTHORIZATION ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +NOTICE: could not create an index on materialized view "ivm_rls2" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +RESET SESSION AUTHORIZATION; +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +-- +(1 row) + +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + id | data | owner | num +----+-------+----------+--------- + 2 | bar | ivm_user | two + 3 | baz_2 | ivm_user | three_2 + 6 | corge | ivm_user | six +(3 rows) + +-- automatic index creation +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; +NOTICE: created index "mv_idx1_index" on materialized view "mv_idx1" +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; +NOTICE: created index "mv_idx2_index" on materialized view "mv_idx2" +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; +NOTICE: created index "mv_idx3_index" on materialized view "mv_idx3" +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +NOTICE: could not create an index on materialized view "mv_idx4" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; +NOTICE: could not create an index on materialized view "mv_idx5" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +-- cleanup +DROP TABLE rls_tbl CASCADE; +NOTICE: drop cascades to 2 other objects +DETAIL: drop cascades to materialized view ivm_rls +drop cascades to materialized view ivm_rls2 +DROP TABLE num_tbl CASCADE; +DROP USER ivm_user; +DROP USER ivm_admin; +DROP TABLE mv_base_b CASCADE; +NOTICE: drop cascades to 3 other objects +DETAIL: drop cascades to materialized view mv_ivm_1 +drop cascades to view b_view +drop cascades to materialized view b_mview +DROP TABLE mv_base_a CASCADE; diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index 5ac6e871f5..64c910af65 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -78,7 +78,7 @@ test: brin_bloom brin_multi # psql depends on create_am # amutils depends on geometry, create_index_spgist, hash_index, brin # ---------- -test: create_table_like alter_generic alter_operator misc async dbsize merge misc_functions sysviews tsrf tid tidscan tidrangescan collate.utf8 collate.icu.utf8 incremental_sort create_role without_overlaps +test: create_table_like alter_generic alter_operator misc async dbsize merge misc_functions sysviews tsrf tid tidscan tidrangescan collate.utf8 collate.icu.utf8 incremental_sort create_role without_overlaps incremental_matview # collate.linux.utf8 and collate.icu.utf8 tests cannot be run in parallel with each other test: rules psql psql_crosstab amutils stats_ext collate.linux.utf8 collate.windows.win1252 diff --git a/src/test/regress/sql/incremental_matview.sql b/src/test/regress/sql/incremental_matview.sql new file mode 100644 index 0000000000..82686f9324 --- /dev/null +++ b/src/test/regress/sql/incremental_matview.sql @@ -0,0 +1,533 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (i int, j int); +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +CREATE TABLE mv_base_b (i int, k int); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); + +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +REFRESH MATERIALIZED VIEW mv_ivm_1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; + +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; +ROLLBACK; + +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +DROP MATERIALIZED VIEW mv_ivm_rename; + +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +DROP MATERIALIZED VIEW mv_ivm_unique; + +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +ROLLBACK; + +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +ROLLBACK; + +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +ROLLBACK; + +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +ROLLBACK; + +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +ROLLBACK; + +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min; + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); + +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; +ROLLBACK; + +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +SELECT * FROM mv_self ORDER BY v1; +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; +SELECT * FROM mv_self ORDER BY v1; + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + +ROLLBACK; + +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +SELECT * FROM mv ORDER BY v1; +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; +SELECT * FROM mv ORDER BY v1; +ROLLBACK; + +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +SELECT * FROM mv_ri ORDER BY i1; +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; +ROLLBACK; + +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +-- IMMV containing user defined type +BEGIN; + +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); + +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; + +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); + +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); + +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + +ROLLBACK; + +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; + +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; + +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; + +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; + +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; + +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); + +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; + +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); + +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ROLLBACK; + +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; + +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; + +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; + +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; + +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; + +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; + +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); + +-- views containing base tables with Row Level Security +DROP USER IF EXISTS ivm_admin; +DROP USER IF EXISTS ivm_user; +CREATE USER ivm_admin; +CREATE USER ivm_user; + +--- create a table with RLS +SET SESSION AUTHORIZATION ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); + +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; + +--- create a view owned by ivm_user +SET SESSION AUTHORIZATION ivm_user; + +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; +RESET SESSION AUTHORIZATION; + +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'ivm_user' WHERE id = 2) +SELECT; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- +SET SESSION AUTHORIZATION ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +RESET SESSION AUTHORIZATION; + +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + +-- automatic index creation +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); + +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; + +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; + +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; + +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; + +-- cleanup + +DROP TABLE rls_tbl CASCADE; +DROP TABLE num_tbl CASCADE; +DROP USER ivm_user; +DROP USER ivm_admin; + +DROP TABLE mv_base_b CASCADE; +DROP TABLE mv_base_a CASCADE; -- 2.25.1 --Multipart=_Fri__29_Mar_2024_23_47_00_+0900_KGpmmDOIs1266Ib1 Content-Type: text/x-diff; name="v31-0011-Add-documentations-about-Incremental-View-Mainte.patch" Content-Disposition: attachment; filename="v31-0011-Add-documentations-about-Incremental-View-Mainte.patch" Content-Transfer-Encoding: 7bit ^ permalink raw reply [nested|flat] 78+ messages in thread
* [PATCH v23 09/15] Add regression tests for Incremental View Maintenance @ 2021-03-10 02:11 Takuma Hoshiai <[email protected]> 0 siblings, 0 replies; 78+ messages in thread From: Takuma Hoshiai @ 2021-03-10 02:11 UTC (permalink / raw) --- .../regress/expected/incremental_matview.out | 799 ++++++++++++++++++ src/test/regress/parallel_schedule | 2 +- src/test/regress/sql/incremental_matview.sql | 400 +++++++++ 3 files changed, 1200 insertions(+), 1 deletion(-) create mode 100644 src/test/regress/expected/incremental_matview.out create mode 100644 src/test/regress/sql/incremental_matview.sql diff --git a/src/test/regress/expected/incremental_matview.out b/src/test/regress/expected/incremental_matview.out new file mode 100644 index 0000000000..fe5bc734e2 --- /dev/null +++ b/src/test/regress/expected/incremental_matview.out @@ -0,0 +1,799 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (i int, j int); +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +CREATE TABLE mv_base_b (i int, k int); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +NOTICE: could not create an index on materialized view "mv_ivm_1" automatically +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ERROR: materialized view "mv_ivm_1" has not been populated +HINT: Use the REFRESH MATERIALIZED VIEW command. +REFRESH MATERIALIZED VIEW mv_ivm_1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_rename_index" on materialized view "mv_ivm_rename" +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +ERROR: IVM column can not be renamed +DROP MATERIALIZED VIEW mv_ivm_rename; +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_unique_index" on materialized view "mv_ivm_unique" +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +ERROR: unique index creation on IVM columns is not supported +DROP MATERIALIZED VIEW mv_ivm_unique; +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +NOTICE: could not create an index on materialized view "mv_ivm_func" automatically +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +NOTICE: could not create an index on materialized view "mv_ivm_no_tbl" automatically +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_duplicate" automatically +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +NOTICE: created index "mv_ivm_distinct_index" on materialized view "mv_ivm_distinct" +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 20 + 30 + 40 + 50 +(6 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +ROLLBACK; +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 120 | 2 | 60.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+---------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 220 | 2 | 110.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 20 | 1 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 120 | 2 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +ROLLBACK; +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 150 | 5 | 30.0000000000000000 +(1 row) + +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 210 | 6 | 35.0000000000000000 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +NOTICE: created index "mv_ivm_avg_bug_index" on materialized view "mv_ivm_avg_bug" +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 3 | 3.3333333333333333 + 2 | 80 | 3 | 26.6666666666666667 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_min_max_index" on materialized view "mv_ivm_min_max" +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 10 + 2 | 20 | 20 + 3 | 30 | 30 + 4 | 40 | 40 + 5 | 50 | 50 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 12 + 2 | 20 | 22 + 3 | 30 | 32 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 11 | 12 + 2 | 20 | 22 + 3 | 30 | 31 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min_max" automatically +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 50 +(1 row) + +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 0 | 70 +(1 row) + +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 60 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + | +(1 row) + +ROLLBACK; +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +NOTICE: could not create an index on materialized view "mv_self" automatically +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +----+---- + 10 | 10 + 20 | 20 + 30 | 30 +(3 rows) + +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 30 | 30 + 40 | 40 + 200 | 200 +(3 rows) + +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 130 | 130 + 300 | 300 +(4 rows) + +ROLLBACK; +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +NOTICE: could not create an index on materialized view "mv" automatically +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY v1; + v1 | v2 +----+----- + 10 | 100 + 20 | 200 + 30 | 300 +(3 rows) + +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv ORDER BY v1; + v1 | v2 +------+----- + 10 | 100 + 11 | 100 + 1020 | 200 + 1020 | 222 +(4 rows) + +ROLLBACK; +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +NOTICE: created index "mv_ri_index" on materialized view "mv_ri" +SELECT * FROM mv_ri ORDER BY i1; + i1 | i2 +----+---- + 1 | 1 + 2 | 2 + 3 | 3 +(3 rows) + +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; + i1 | i2 +----+---- + 3 | 3 + 10 | 10 +(2 rows) + +ROLLBACK; +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | +(2 rows) + +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | 20 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i +--- +(0 rows) + +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; + i +--- + 1 + +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 30 + | 3 +(2 rows) + +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 300 + | 30 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 1 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 4 +(1 row) + +ROLLBACK; +-- IMMV containing user defined type +BEGIN; +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: return type mytype is only a shell +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: argument type mytype is only a shell +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +NOTICE: could not create an index on materialized view "mv_mytype" automatically +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + x +--- + 1 +(1 row) + +ROLLBACK; +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +ERROR: OUTER JOIN is not supported on incrementally maintainable materialized view +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +ERROR: CTE is not supported on incrementally maintainable materialized view +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +ERROR: ORDER BY clause is not supported on incrementally maintainable materialized view +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; +ERROR: HAVING clause is not supported on incrementally maintainable materialized view +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; +ERROR: mutable function is not supported on incrementally maintainable materialized view +HINT: functions must be marked IMMUTABLE +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; +ERROR: LIMIT/OFFSET clause is not supported on incrementally maintainable materialized view +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; +ERROR: DISTINCT ON is not supported on incrementally maintainable materialized view +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); +ERROR: TABLESAMPLE clause is not supported on incrementally maintainable materialized view +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; +ERROR: window functions are not supported on incrementally maintainable materialized view +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +ERROR: aggregate function with FILTER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +ERROR: aggregate function with DISTINCT arguments is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +ERROR: aggregate function with ORDER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); +ERROR: GROUPING SETS, ROLLUP, or CUBE clauses is not supported on incrementally maintainable materialized view +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ERROR: inheritance parent is not supported on incrementally maintainable materialized view +ROLLBACK; +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; +ERROR: UNION/INTERSECT/EXCEPT statements are not supported on incrementally maintainable materialized view +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; +ERROR: empty target list is not supported on incrementally maintainable materialized view +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; +ERROR: FOR UPDATE/SHARE clause is not supported on incrementally maintainable materialized view +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; +ERROR: column name __ivm_count__ is not supported on incrementally maintainable materialized view +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; +ERROR: GROUP BY expression not appeared in select list is not supported on incrementally maintainable materialized view +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); +ERROR: VALUES is not supported on incrementally maintainable materialized view +-- base table which has row level security +DROP USER IF EXISTS ivm_admin; +NOTICE: role "ivm_admin" does not exist, skipping +DROP USER IF EXISTS ivm_user; +NOTICE: role "ivm_user" does not exist, skipping +CREATE USER ivm_admin; +CREATE USER ivm_user; +SET SESSION AUTHORIZATION ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'); +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +CREATE POLICY rls_tbl_policy2 ON rls_tbl FOR INSERT TO PUBLIC WITH CHECK(current_user LIKE 'ivm_%'); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; +SET SESSION AUTHORIZATION ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +NOTICE: could not create an index on materialized view "ivm_rls" automatically +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+---------- + 1 | foo | ivm_user +(1 row) + +INSERT INTO rls_tbl VALUES + (3,'baz','ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+---------- + 1 | foo | ivm_user + 3 | baz | ivm_user +(2 rows) + +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +NOTICE: could not create an index on materialized view "ivm_rls2" automatically +HINT: Create an index on the materialized view for efficient incremental maintenance. +RESET SESSION AUTHORIZATION; +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +-- +(1 row) + +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + id | data | owner | num +----+-------+----------+--------- + 1 | foo | ivm_user | one + 3 | baz_2 | ivm_user | three_2 +(2 rows) + +DROP TABLE rls_tbl CASCADE; +NOTICE: drop cascades to 2 other objects +DETAIL: drop cascades to materialized view ivm_rls +drop cascades to materialized view ivm_rls2 +DROP TABLE num_tbl CASCADE; +DROP USER ivm_user; +DROP USER ivm_admin; +DROP TABLE mv_base_b CASCADE; +NOTICE: drop cascades to 3 other objects +DETAIL: drop cascades to materialized view mv_ivm_1 +drop cascades to view b_view +drop cascades to materialized view b_mview +DROP TABLE mv_base_a CASCADE; diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index 7be89178f0..b0350f47dd 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -86,7 +86,7 @@ test: brin_bloom brin_multi # ---------- # Another group of parallel tests # ---------- -test: create_table_like alter_generic alter_operator misc async dbsize misc_functions sysviews tsrf tid tidscan tidrangescan collate.icu.utf8 incremental_sort +test: create_table_like alter_generic alter_operator misc async dbsize misc_functions sysviews tsrf tid tidscan tidrangescan collate.icu.utf8 incremental_sort incremental_matview # rules cannot run concurrently with any test that creates # a view or rule in the public schema diff --git a/src/test/regress/sql/incremental_matview.sql b/src/test/regress/sql/incremental_matview.sql new file mode 100644 index 0000000000..311e9b96fb --- /dev/null +++ b/src/test/regress/sql/incremental_matview.sql @@ -0,0 +1,400 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (i int, j int); +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +CREATE TABLE mv_base_b (i int, k int); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); + +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +REFRESH MATERIALIZED VIEW mv_ivm_1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +DROP MATERIALIZED VIEW mv_ivm_rename; + +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +DROP MATERIALIZED VIEW mv_ivm_unique; + +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +ROLLBACK; + +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +ROLLBACK; + +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +ROLLBACK; + +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +ROLLBACK; + +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +ROLLBACK; + +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +ROLLBACK; + +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +SELECT * FROM mv_self ORDER BY v1; +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; +SELECT * FROM mv_self ORDER BY v1; +ROLLBACK; + +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +SELECT * FROM mv ORDER BY v1; +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; +SELECT * FROM mv ORDER BY v1; +ROLLBACK; + +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +SELECT * FROM mv_ri ORDER BY i1; +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; +ROLLBACK; + +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +-- IMMV containing user defined type +BEGIN; + +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); + +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; + +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); + +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); + +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + +ROLLBACK; + +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; + +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; + +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; + +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; + +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; + +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); + +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; + +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); + +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ROLLBACK; + +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; + +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; + +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; + +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; + +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; + +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; + +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); + +-- base table which has row level security +DROP USER IF EXISTS ivm_admin; +DROP USER IF EXISTS ivm_user; +CREATE USER ivm_admin; +CREATE USER ivm_user; +SET SESSION AUTHORIZATION ivm_admin; + +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'); +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +CREATE POLICY rls_tbl_policy2 ON rls_tbl FOR INSERT TO PUBLIC WITH CHECK(current_user LIKE 'ivm_%'); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; + +SET SESSION AUTHORIZATION ivm_user; + +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; +INSERT INTO rls_tbl VALUES + (3,'baz','ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); + +RESET SESSION AUTHORIZATION; + +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + +DROP TABLE rls_tbl CASCADE; +DROP TABLE num_tbl CASCADE; +DROP USER ivm_user; +DROP USER ivm_admin; + +DROP TABLE mv_base_b CASCADE; +DROP TABLE mv_base_a CASCADE; -- 2.17.1 --Multipart=_Mon__2_Aug_2021_15_28_34_+0900_wlHCjIpnD/FrGAKu Content-Type: text/x-diff; name="v23-0010-Add-documentations-about-Incremental-View-Mainte.patch" Content-Disposition: attachment; filename="v23-0010-Add-documentations-about-Incremental-View-Mainte.patch" Content-Transfer-Encoding: 7bit ^ permalink raw reply [nested|flat] 78+ messages in thread
* [PATCH v29 10/11] Add regression tests for Incremental View Maintenance @ 2021-03-10 02:11 Takuma Hoshiai <[email protected]> 0 siblings, 0 replies; 78+ messages in thread From: Takuma Hoshiai @ 2021-03-10 02:11 UTC (permalink / raw) --- .../regress/expected/incremental_matview.out | 1030 +++++++++++++++++ src/test/regress/parallel_schedule | 2 +- src/test/regress/sql/incremental_matview.sql | 533 +++++++++ 3 files changed, 1564 insertions(+), 1 deletion(-) create mode 100644 src/test/regress/expected/incremental_matview.out create mode 100644 src/test/regress/sql/incremental_matview.sql diff --git a/src/test/regress/expected/incremental_matview.out b/src/test/regress/expected/incremental_matview.out new file mode 100644 index 0000000000..8946d09f5d --- /dev/null +++ b/src/test/regress/expected/incremental_matview.out @@ -0,0 +1,1030 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (i int, j int); +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +CREATE TABLE mv_base_b (i int, k int); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ERROR: materialized view "mv_ivm_1" has not been populated +HINT: Use the REFRESH MATERIALIZED VIEW command. +REFRESH MATERIALIZED VIEW mv_ivm_1; +NOTICE: could not create an index on materialized view "mv_ivm_1" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 17 +(1 row) + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 1 +(1 row) + +ROLLBACK; +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_rename_index" on materialized view "mv_ivm_rename" +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +ERROR: IVM column can not be renamed +DROP MATERIALIZED VIEW mv_ivm_rename; +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_unique_index" on materialized view "mv_ivm_unique" +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +ERROR: unique index creation on IVM columns is not supported +DROP MATERIALIZED VIEW mv_ivm_unique; +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +NOTICE: could not create an index on materialized view "mv_ivm_func" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +NOTICE: could not create an index on materialized view "mv_ivm_no_tbl" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_duplicate" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +NOTICE: created index "mv_ivm_distinct_index" on materialized view "mv_ivm_distinct" +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 20 + 30 + 40 + 50 +(6 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +ROLLBACK; +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 120 | 2 | 60.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+---------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 220 | 2 | 110.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 20 | 1 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 120 | 2 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; + sum | count +-----+------- +(0 rows) + +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; + i | sum | count +---+-----+------- +(0 rows) + +ROLLBACK; +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 150 | 5 | 30.0000000000000000 +(1 row) + +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 210 | 6 | 35.0000000000000000 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +NOTICE: created index "mv_ivm_avg_bug_index" on materialized view "mv_ivm_avg_bug" +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 3 | 3.3333333333333333 + 2 | 80 | 3 | 26.6666666666666667 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_min_max_index" on materialized view "mv_ivm_min_max" +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 10 + 2 | 20 | 20 + 3 | 30 | 30 + 4 | 40 | 40 + 5 | 50 | 50 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 12 + 2 | 20 | 22 + 3 | 30 | 32 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 11 | 12 + 2 | 20 | 22 + 3 | 30 | 31 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min_max" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 50 +(1 row) + +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 0 | 70 +(1 row) + +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 60 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + | +(1 row) + +ROLLBACK; +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min; + min +----- + 10 +(1 row) + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + min +----- + 20 +(1 row) + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; + min +----- + 30 +(1 row) + +ROLLBACK; +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | sum +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | b +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ERROR: too many column names were specified +ROLLBACK; +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +NOTICE: could not create an index on materialized view "mv_self" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +----+---- + 10 | 10 + 20 | 20 + 30 | 30 +(3 rows) + +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 30 | 30 + 40 | 40 + 200 | 200 +(3 rows) + +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 130 | 130 + 300 | 300 +(4 rows) + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 70 | 70 + 70 | 77 + 77 | 70 + 77 | 77 + 130 | 130 + 300 | 300 +(8 rows) + +ROLLBACK; +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY v1; + v1 | v2 +----+----- + 10 | 100 + 20 | 200 + 30 | 300 +(3 rows) + +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv ORDER BY v1; + v1 | v2 +------+----- + 10 | 100 + 11 | 100 + 1020 | 200 + 1020 | 222 +(4 rows) + +ROLLBACK; +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +NOTICE: created index "mv_ri_index" on materialized view "mv_ri" +SELECT * FROM mv_ri ORDER BY i1; + i1 | i2 +----+---- + 1 | 1 + 2 | 2 + 3 | 3 +(3 rows) + +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; + i1 | i2 +----+---- + 3 | 3 + 10 | 10 +(2 rows) + +ROLLBACK; +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | +(2 rows) + +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | 20 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i +--- +(0 rows) + +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; + i +--- + 1 + +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 30 + | 3 +(2 rows) + +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 300 + | 30 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 1 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 4 +(1 row) + +ROLLBACK; +-- IMMV containing user defined type +BEGIN; +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: return type mytype is only a shell +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: argument type mytype is only a shell +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +NOTICE: could not create an index on materialized view "mv_mytype" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + x +--- + 1 +(1 row) + +ROLLBACK; +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +ERROR: OUTER JOIN is not supported on incrementally maintainable materialized view +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +ERROR: CTE is not supported on incrementally maintainable materialized view +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +ERROR: ORDER BY clause is not supported on incrementally maintainable materialized view +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; +ERROR: HAVING clause is not supported on incrementally maintainable materialized view +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; +ERROR: mutable function is not supported on incrementally maintainable materialized view +HINT: functions must be marked IMMUTABLE +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; +ERROR: LIMIT/OFFSET clause is not supported on incrementally maintainable materialized view +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; +ERROR: DISTINCT ON is not supported on incrementally maintainable materialized view +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); +ERROR: TABLESAMPLE clause is not supported on incrementally maintainable materialized view +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; +ERROR: window functions are not supported on incrementally maintainable materialized view +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +ERROR: aggregate function with FILTER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +ERROR: aggregate function with DISTINCT arguments is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +ERROR: aggregate function with ORDER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); +ERROR: GROUPING SETS, ROLLUP, or CUBE clauses is not supported on incrementally maintainable materialized view +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ERROR: inheritance parent is not supported on incrementally maintainable materialized view +ROLLBACK; +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; +ERROR: UNION/INTERSECT/EXCEPT statements are not supported on incrementally maintainable materialized view +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; +ERROR: empty target list is not supported on incrementally maintainable materialized view +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; +ERROR: FOR UPDATE/SHARE clause is not supported on incrementally maintainable materialized view +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; +ERROR: column name __ivm_count__ is not supported on incrementally maintainable materialized view +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; +ERROR: GROUP BY expression not appearing in select list is not supported on incrementally maintainable materialized view +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); +ERROR: VALUES is not supported on incrementally maintainable materialized view +-- views containing base tables with Row Level Security +DROP USER IF EXISTS ivm_admin; +NOTICE: role "ivm_admin" does not exist, skipping +DROP USER IF EXISTS ivm_user; +NOTICE: role "ivm_user" does not exist, skipping +CREATE USER ivm_admin; +CREATE USER ivm_user; +--- create a table with RLS +SET SESSION AUTHORIZATION ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; +--- create a view owned by ivm_user +SET SESSION AUTHORIZATION ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +NOTICE: could not create an index on materialized view "ivm_rls" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+---------- + 1 | foo | ivm_user +(1 row) + +RESET SESSION AUTHORIZATION; +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+---------- + 1 | foo | ivm_user + 3 | baz | ivm_user +(2 rows) + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'ivm_user' WHERE id = 2) +SELECT; +-- +(1 row) + +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+-------+---------- + 2 | bar | ivm_user + 3 | baz | ivm_user + 6 | corge | ivm_user +(3 rows) + +--- +SET SESSION AUTHORIZATION ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +NOTICE: could not create an index on materialized view "ivm_rls2" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +RESET SESSION AUTHORIZATION; +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +-- +(1 row) + +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + id | data | owner | num +----+-------+----------+--------- + 2 | bar | ivm_user | two + 3 | baz_2 | ivm_user | three_2 + 6 | corge | ivm_user | six +(3 rows) + +-- automatic index creation +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; +NOTICE: created index "mv_idx1_index" on materialized view "mv_idx1" +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; +NOTICE: created index "mv_idx2_index" on materialized view "mv_idx2" +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; +NOTICE: created index "mv_idx3_index" on materialized view "mv_idx3" +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +NOTICE: could not create an index on materialized view "mv_idx4" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; +NOTICE: could not create an index on materialized view "mv_idx5" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +-- cleanup +DROP TABLE rls_tbl CASCADE; +NOTICE: drop cascades to 2 other objects +DETAIL: drop cascades to materialized view ivm_rls +drop cascades to materialized view ivm_rls2 +DROP TABLE num_tbl CASCADE; +DROP USER ivm_user; +DROP USER ivm_admin; +DROP TABLE mv_base_b CASCADE; +NOTICE: drop cascades to 3 other objects +DETAIL: drop cascades to materialized view mv_ivm_1 +drop cascades to view b_view +drop cascades to materialized view b_mview +DROP TABLE mv_base_a CASCADE; diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index 4df9d8503b..21f7247a07 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -78,7 +78,7 @@ test: brin_bloom brin_multi # psql depends on create_am # amutils depends on geometry, create_index_spgist, hash_index, brin # ---------- -test: create_table_like alter_generic alter_operator misc async dbsize merge misc_functions sysviews tsrf tid tidscan tidrangescan collate.icu.utf8 incremental_sort create_role +test: create_table_like alter_generic alter_operator misc async dbsize merge misc_functions sysviews tsrf tid tidscan tidrangescan collate.icu.utf8 incremental_sort create_role incremental_matview # collate.*.utf8 tests cannot be run in parallel with each other test: rules psql psql_crosstab amutils stats_ext collate.linux.utf8 collate.windows.win1252 diff --git a/src/test/regress/sql/incremental_matview.sql b/src/test/regress/sql/incremental_matview.sql new file mode 100644 index 0000000000..82686f9324 --- /dev/null +++ b/src/test/regress/sql/incremental_matview.sql @@ -0,0 +1,533 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (i int, j int); +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +CREATE TABLE mv_base_b (i int, k int); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); + +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +REFRESH MATERIALIZED VIEW mv_ivm_1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; + +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; +ROLLBACK; + +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +DROP MATERIALIZED VIEW mv_ivm_rename; + +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +DROP MATERIALIZED VIEW mv_ivm_unique; + +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +ROLLBACK; + +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +ROLLBACK; + +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +ROLLBACK; + +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +ROLLBACK; + +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +ROLLBACK; + +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min; + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); + +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; +ROLLBACK; + +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +SELECT * FROM mv_self ORDER BY v1; +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; +SELECT * FROM mv_self ORDER BY v1; + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + +ROLLBACK; + +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +SELECT * FROM mv ORDER BY v1; +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; +SELECT * FROM mv ORDER BY v1; +ROLLBACK; + +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +SELECT * FROM mv_ri ORDER BY i1; +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; +ROLLBACK; + +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +-- IMMV containing user defined type +BEGIN; + +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); + +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; + +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); + +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); + +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + +ROLLBACK; + +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; + +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; + +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; + +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; + +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; + +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); + +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; + +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); + +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ROLLBACK; + +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; + +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; + +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; + +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; + +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; + +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; + +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); + +-- views containing base tables with Row Level Security +DROP USER IF EXISTS ivm_admin; +DROP USER IF EXISTS ivm_user; +CREATE USER ivm_admin; +CREATE USER ivm_user; + +--- create a table with RLS +SET SESSION AUTHORIZATION ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); + +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; + +--- create a view owned by ivm_user +SET SESSION AUTHORIZATION ivm_user; + +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; +RESET SESSION AUTHORIZATION; + +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'ivm_user' WHERE id = 2) +SELECT; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- +SET SESSION AUTHORIZATION ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +RESET SESSION AUTHORIZATION; + +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + +-- automatic index creation +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); + +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; + +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; + +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; + +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; + +-- cleanup + +DROP TABLE rls_tbl CASCADE; +DROP TABLE num_tbl CASCADE; +DROP USER ivm_user; +DROP USER ivm_admin; + +DROP TABLE mv_base_b CASCADE; +DROP TABLE mv_base_a CASCADE; -- 2.25.1 --Multipart=_Mon__28_Aug_2023_16_05_30_+0900_b1OvQD_3A3ZMTGvj Content-Type: text/x-diff; name="v29-0011-Add-documentations-about-Incremental-View-Mainte.patch" Content-Disposition: attachment; filename="v29-0011-Add-documentations-about-Incremental-View-Mainte.patch" Content-Transfer-Encoding: 7bit ^ permalink raw reply [nested|flat] 78+ messages in thread
* [PATCH v27 8/9] Add regression tests for Incremental View Maintenance @ 2021-03-10 02:11 Takuma Hoshiai <[email protected]> 0 siblings, 0 replies; 78+ messages in thread From: Takuma Hoshiai @ 2021-03-10 02:11 UTC (permalink / raw) --- .../regress/expected/incremental_matview.out | 840 ++++++++++++++++++ src/test/regress/parallel_schedule | 2 +- src/test/regress/sql/incremental_matview.sql | 424 +++++++++ 3 files changed, 1265 insertions(+), 1 deletion(-) create mode 100644 src/test/regress/expected/incremental_matview.out create mode 100644 src/test/regress/sql/incremental_matview.sql diff --git a/src/test/regress/expected/incremental_matview.out b/src/test/regress/expected/incremental_matview.out new file mode 100644 index 0000000000..201af5f087 --- /dev/null +++ b/src/test/regress/expected/incremental_matview.out @@ -0,0 +1,840 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (i int, j int); +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +CREATE TABLE mv_base_b (i int, k int); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ERROR: materialized view "mv_ivm_1" has not been populated +HINT: Use the REFRESH MATERIALIZED VIEW command. +REFRESH MATERIALIZED VIEW mv_ivm_1; +NOTICE: could not create an index on materialized view "mv_ivm_1" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 13 +(1 row) + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 1 +(1 row) + +ROLLBACK; +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_rename_index" on materialized view "mv_ivm_rename" +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +ERROR: IVM column can not be renamed +DROP MATERIALIZED VIEW mv_ivm_rename; +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_unique_index" on materialized view "mv_ivm_unique" +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +ERROR: unique index creation on IVM columns is not supported +DROP MATERIALIZED VIEW mv_ivm_unique; +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +NOTICE: could not create an index on materialized view "mv_ivm_func" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +NOTICE: could not create an index on materialized view "mv_ivm_no_tbl" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_duplicate" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +NOTICE: created index "mv_ivm_distinct_index" on materialized view "mv_ivm_distinct" +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 20 + 30 + 40 + 50 +(6 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +ROLLBACK; +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 120 | 2 | 60.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+---------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 220 | 2 | 110.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 20 | 1 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 120 | 2 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +ROLLBACK; +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 150 | 5 | 30.0000000000000000 +(1 row) + +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 210 | 6 | 35.0000000000000000 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +NOTICE: created index "mv_ivm_avg_bug_index" on materialized view "mv_ivm_avg_bug" +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 3 | 3.3333333333333333 + 2 | 80 | 3 | 26.6666666666666667 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_min_max_index" on materialized view "mv_ivm_min_max" +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 10 + 2 | 20 | 20 + 3 | 30 | 30 + 4 | 40 | 40 + 5 | 50 | 50 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 12 + 2 | 20 | 22 + 3 | 30 | 32 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 11 | 12 + 2 | 20 | 22 + 3 | 30 | 31 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min_max" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 50 +(1 row) + +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 0 | 70 +(1 row) + +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 60 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + | +(1 row) + +ROLLBACK; +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +NOTICE: could not create an index on materialized view "mv_self" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +----+---- + 10 | 10 + 20 | 20 + 30 | 30 +(3 rows) + +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 30 | 30 + 40 | 40 + 200 | 200 +(3 rows) + +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 130 | 130 + 300 | 300 +(4 rows) + +ROLLBACK; +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY v1; + v1 | v2 +----+----- + 10 | 100 + 20 | 200 + 30 | 300 +(3 rows) + +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv ORDER BY v1; + v1 | v2 +------+----- + 10 | 100 + 11 | 100 + 1020 | 200 + 1020 | 222 +(4 rows) + +ROLLBACK; +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +NOTICE: created index "mv_ri_index" on materialized view "mv_ri" +SELECT * FROM mv_ri ORDER BY i1; + i1 | i2 +----+---- + 1 | 1 + 2 | 2 + 3 | 3 +(3 rows) + +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; + i1 | i2 +----+---- + 3 | 3 + 10 | 10 +(2 rows) + +ROLLBACK; +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | +(2 rows) + +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | 20 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i +--- +(0 rows) + +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; + i +--- + 1 + +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 30 + | 3 +(2 rows) + +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 300 + | 30 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 1 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 4 +(1 row) + +ROLLBACK; +-- IMMV containing user defined type +BEGIN; +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: return type mytype is only a shell +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: argument type mytype is only a shell +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +NOTICE: could not create an index on materialized view "mv_mytype" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + x +--- + 1 +(1 row) + +ROLLBACK; +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +ERROR: OUTER JOIN is not supported on incrementally maintainable materialized view +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +ERROR: CTE is not supported on incrementally maintainable materialized view +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +ERROR: ORDER BY clause is not supported on incrementally maintainable materialized view +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; +ERROR: HAVING clause is not supported on incrementally maintainable materialized view +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; +ERROR: mutable function is not supported on incrementally maintainable materialized view +HINT: functions must be marked IMMUTABLE +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; +ERROR: LIMIT/OFFSET clause is not supported on incrementally maintainable materialized view +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; +ERROR: DISTINCT ON is not supported on incrementally maintainable materialized view +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); +ERROR: TABLESAMPLE clause is not supported on incrementally maintainable materialized view +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; +ERROR: window functions are not supported on incrementally maintainable materialized view +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +ERROR: aggregate function with FILTER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +ERROR: aggregate function with DISTINCT arguments is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +ERROR: aggregate function with ORDER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); +ERROR: GROUPING SETS, ROLLUP, or CUBE clauses is not supported on incrementally maintainable materialized view +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ERROR: inheritance parent is not supported on incrementally maintainable materialized view +ROLLBACK; +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; +ERROR: UNION/INTERSECT/EXCEPT statements are not supported on incrementally maintainable materialized view +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; +ERROR: empty target list is not supported on incrementally maintainable materialized view +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; +ERROR: FOR UPDATE/SHARE clause is not supported on incrementally maintainable materialized view +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; +ERROR: column name __ivm_count__ is not supported on incrementally maintainable materialized view +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; +ERROR: GROUP BY expression not appearing in select list is not supported on incrementally maintainable materialized view +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); +ERROR: VALUES is not supported on incrementally maintainable materialized view +-- base table which has row level security +DROP USER IF EXISTS ivm_admin; +NOTICE: role "ivm_admin" does not exist, skipping +DROP USER IF EXISTS ivm_user; +NOTICE: role "ivm_user" does not exist, skipping +CREATE USER ivm_admin; +CREATE USER ivm_user; +SET SESSION AUTHORIZATION ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'); +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +CREATE POLICY rls_tbl_policy2 ON rls_tbl FOR INSERT TO PUBLIC WITH CHECK(current_user LIKE 'ivm_%'); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; +SET SESSION AUTHORIZATION ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +NOTICE: could not create an index on materialized view "ivm_rls" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+---------- + 1 | foo | ivm_user +(1 row) + +INSERT INTO rls_tbl VALUES + (3,'baz','ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+---------- + 1 | foo | ivm_user + 3 | baz | ivm_user +(2 rows) + +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +NOTICE: could not create an index on materialized view "ivm_rls2" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +RESET SESSION AUTHORIZATION; +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +-- +(1 row) + +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + id | data | owner | num +----+-------+----------+--------- + 1 | foo | ivm_user | one + 3 | baz_2 | ivm_user | three_2 +(2 rows) + +DROP TABLE rls_tbl CASCADE; +NOTICE: drop cascades to 2 other objects +DETAIL: drop cascades to materialized view ivm_rls +drop cascades to materialized view ivm_rls2 +DROP TABLE num_tbl CASCADE; +DROP USER ivm_user; +DROP USER ivm_admin; +DROP TABLE mv_base_b CASCADE; +NOTICE: drop cascades to 3 other objects +DETAIL: drop cascades to materialized view mv_ivm_1 +drop cascades to view b_view +drop cascades to materialized view b_mview +DROP TABLE mv_base_a CASCADE; diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index 103e11483d..3027f4e78c 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -86,7 +86,7 @@ test: brin_bloom brin_multi # psql depends on create_am # amutils depends on geometry, create_index_spgist, hash_index, brin # ---------- -test: create_table_like alter_generic alter_operator misc async dbsize merge misc_functions sysviews tsrf tid tidscan tidrangescan collate.icu.utf8 incremental_sort create_role +test: create_table_like alter_generic alter_operator misc async dbsize merge misc_functions sysviews tsrf tid tidscan tidrangescan collate.icu.utf8 incremental_sort create_role incremental_matview # collate.*.utf8 tests cannot be run in parallel with each other test: rules psql psql_crosstab amutils stats_ext collate.linux.utf8 diff --git a/src/test/regress/sql/incremental_matview.sql b/src/test/regress/sql/incremental_matview.sql new file mode 100644 index 0000000000..a4ce2c741e --- /dev/null +++ b/src/test/regress/sql/incremental_matview.sql @@ -0,0 +1,424 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (i int, j int); +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +CREATE TABLE mv_base_b (i int, k int); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); + +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +REFRESH MATERIALIZED VIEW mv_ivm_1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; + +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; +ROLLBACK; + +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +DROP MATERIALIZED VIEW mv_ivm_rename; + +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +DROP MATERIALIZED VIEW mv_ivm_unique; + +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +ROLLBACK; + +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +ROLLBACK; + +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +ROLLBACK; + +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +ROLLBACK; + +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +ROLLBACK; + +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +ROLLBACK; + +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +SELECT * FROM mv_self ORDER BY v1; +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; +SELECT * FROM mv_self ORDER BY v1; +ROLLBACK; + +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +SELECT * FROM mv ORDER BY v1; +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; +SELECT * FROM mv ORDER BY v1; +ROLLBACK; + +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +SELECT * FROM mv_ri ORDER BY i1; +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; +ROLLBACK; + +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +-- IMMV containing user defined type +BEGIN; + +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); + +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; + +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); + +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); + +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + +ROLLBACK; + +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; + +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; + +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; + +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; + +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; + +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); + +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; + +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); + +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ROLLBACK; + +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; + +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; + +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; + +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; + +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; + +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; + +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); + +-- base table which has row level security +DROP USER IF EXISTS ivm_admin; +DROP USER IF EXISTS ivm_user; +CREATE USER ivm_admin; +CREATE USER ivm_user; +SET SESSION AUTHORIZATION ivm_admin; + +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'); +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +CREATE POLICY rls_tbl_policy2 ON rls_tbl FOR INSERT TO PUBLIC WITH CHECK(current_user LIKE 'ivm_%'); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; + +SET SESSION AUTHORIZATION ivm_user; + +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; +INSERT INTO rls_tbl VALUES + (3,'baz','ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); + +RESET SESSION AUTHORIZATION; + +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + +DROP TABLE rls_tbl CASCADE; +DROP TABLE num_tbl CASCADE; +DROP USER ivm_user; +DROP USER ivm_admin; + +DROP TABLE mv_base_b CASCADE; +DROP TABLE mv_base_a CASCADE; -- 2.17.1 --Multipart=_Fri__22_Apr_2022_11_29_39_+0900_ZOAC7UMt5e8j1Nvx Content-Type: text/x-diff; name="v27-0009-Add-documentations-about-Incremental-View-Mainte.patch" Content-Disposition: attachment; filename="v27-0009-Add-documentations-about-Incremental-View-Mainte.patch" Content-Transfer-Encoding: 7bit ^ permalink raw reply [nested|flat] 78+ messages in thread
* [PATCH v26 09/10] Add regression tests for Incremental View Maintenance @ 2021-03-10 02:11 Takuma Hoshiai <[email protected]> 0 siblings, 0 replies; 78+ messages in thread From: Takuma Hoshiai @ 2021-03-10 02:11 UTC (permalink / raw) --- .../regress/expected/incremental_matview.out | 812 ++++++++++++++++++ src/test/regress/parallel_schedule | 2 +- src/test/regress/sql/incremental_matview.sql | 400 +++++++++ 3 files changed, 1213 insertions(+), 1 deletion(-) create mode 100644 src/test/regress/expected/incremental_matview.out create mode 100644 src/test/regress/sql/incremental_matview.sql diff --git a/src/test/regress/expected/incremental_matview.out b/src/test/regress/expected/incremental_matview.out new file mode 100644 index 0000000000..7b10fcddbe --- /dev/null +++ b/src/test/regress/expected/incremental_matview.out @@ -0,0 +1,812 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (i int, j int); +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +CREATE TABLE mv_base_b (i int, k int); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ERROR: materialized view "mv_ivm_1" has not been populated +HINT: Use the REFRESH MATERIALIZED VIEW command. +REFRESH MATERIALIZED VIEW mv_ivm_1; +NOTICE: could not create an index on materialized view "mv_ivm_1" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_rename_index" on materialized view "mv_ivm_rename" +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +ERROR: IVM column can not be renamed +DROP MATERIALIZED VIEW mv_ivm_rename; +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_unique_index" on materialized view "mv_ivm_unique" +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +ERROR: unique index creation on IVM columns is not supported +DROP MATERIALIZED VIEW mv_ivm_unique; +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +NOTICE: could not create an index on materialized view "mv_ivm_func" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +NOTICE: could not create an index on materialized view "mv_ivm_no_tbl" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_duplicate" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +NOTICE: created index "mv_ivm_distinct_index" on materialized view "mv_ivm_distinct" +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 20 + 30 + 40 + 50 +(6 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +ROLLBACK; +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 120 | 2 | 60.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+---------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 220 | 2 | 110.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 20 | 1 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 120 | 2 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +ROLLBACK; +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 150 | 5 | 30.0000000000000000 +(1 row) + +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 210 | 6 | 35.0000000000000000 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +NOTICE: created index "mv_ivm_avg_bug_index" on materialized view "mv_ivm_avg_bug" +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 3 | 3.3333333333333333 + 2 | 80 | 3 | 26.6666666666666667 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_min_max_index" on materialized view "mv_ivm_min_max" +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 10 + 2 | 20 | 20 + 3 | 30 | 30 + 4 | 40 | 40 + 5 | 50 | 50 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 12 + 2 | 20 | 22 + 3 | 30 | 32 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 11 | 12 + 2 | 20 | 22 + 3 | 30 | 31 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min_max" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 50 +(1 row) + +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 0 | 70 +(1 row) + +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 60 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + | +(1 row) + +ROLLBACK; +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +NOTICE: could not create an index on materialized view "mv_self" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +----+---- + 10 | 10 + 20 | 20 + 30 | 30 +(3 rows) + +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 30 | 30 + 40 | 40 + 200 | 200 +(3 rows) + +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 130 | 130 + 300 | 300 +(4 rows) + +ROLLBACK; +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY v1; + v1 | v2 +----+----- + 10 | 100 + 20 | 200 + 30 | 300 +(3 rows) + +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv ORDER BY v1; + v1 | v2 +------+----- + 10 | 100 + 11 | 100 + 1020 | 200 + 1020 | 222 +(4 rows) + +ROLLBACK; +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +NOTICE: created index "mv_ri_index" on materialized view "mv_ri" +SELECT * FROM mv_ri ORDER BY i1; + i1 | i2 +----+---- + 1 | 1 + 2 | 2 + 3 | 3 +(3 rows) + +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; + i1 | i2 +----+---- + 3 | 3 + 10 | 10 +(2 rows) + +ROLLBACK; +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | +(2 rows) + +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | 20 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i +--- +(0 rows) + +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; + i +--- + 1 + +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 30 + | 3 +(2 rows) + +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 300 + | 30 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 1 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 4 +(1 row) + +ROLLBACK; +-- IMMV containing user defined type +BEGIN; +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: return type mytype is only a shell +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: argument type mytype is only a shell +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +NOTICE: could not create an index on materialized view "mv_mytype" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + x +--- + 1 +(1 row) + +ROLLBACK; +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +ERROR: OUTER JOIN is not supported on incrementally maintainable materialized view +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +ERROR: CTE is not supported on incrementally maintainable materialized view +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +ERROR: ORDER BY clause is not supported on incrementally maintainable materialized view +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; +ERROR: HAVING clause is not supported on incrementally maintainable materialized view +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; +ERROR: mutable function is not supported on incrementally maintainable materialized view +HINT: functions must be marked IMMUTABLE +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; +ERROR: LIMIT/OFFSET clause is not supported on incrementally maintainable materialized view +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; +ERROR: DISTINCT ON is not supported on incrementally maintainable materialized view +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); +ERROR: TABLESAMPLE clause is not supported on incrementally maintainable materialized view +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; +ERROR: window functions are not supported on incrementally maintainable materialized view +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +ERROR: aggregate function with FILTER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +ERROR: aggregate function with DISTINCT arguments is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +ERROR: aggregate function with ORDER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); +ERROR: GROUPING SETS, ROLLUP, or CUBE clauses is not supported on incrementally maintainable materialized view +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ERROR: inheritance parent is not supported on incrementally maintainable materialized view +ROLLBACK; +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; +ERROR: UNION/INTERSECT/EXCEPT statements are not supported on incrementally maintainable materialized view +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; +ERROR: empty target list is not supported on incrementally maintainable materialized view +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; +ERROR: FOR UPDATE/SHARE clause is not supported on incrementally maintainable materialized view +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; +ERROR: column name __ivm_count__ is not supported on incrementally maintainable materialized view +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; +ERROR: GROUP BY expression not appearing in select list is not supported on incrementally maintainable materialized view +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); +ERROR: VALUES is not supported on incrementally maintainable materialized view +-- base table which has row level security +DROP USER IF EXISTS ivm_admin; +NOTICE: role "ivm_admin" does not exist, skipping +DROP USER IF EXISTS ivm_user; +NOTICE: role "ivm_user" does not exist, skipping +CREATE USER ivm_admin; +CREATE USER ivm_user; +SET SESSION AUTHORIZATION ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'); +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +CREATE POLICY rls_tbl_policy2 ON rls_tbl FOR INSERT TO PUBLIC WITH CHECK(current_user LIKE 'ivm_%'); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; +SET SESSION AUTHORIZATION ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +NOTICE: could not create an index on materialized view "ivm_rls" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+---------- + 1 | foo | ivm_user +(1 row) + +INSERT INTO rls_tbl VALUES + (3,'baz','ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+---------- + 1 | foo | ivm_user + 3 | baz | ivm_user +(2 rows) + +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +NOTICE: could not create an index on materialized view "ivm_rls2" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +RESET SESSION AUTHORIZATION; +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +-- +(1 row) + +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + id | data | owner | num +----+-------+----------+--------- + 1 | foo | ivm_user | one + 3 | baz_2 | ivm_user | three_2 +(2 rows) + +DROP TABLE rls_tbl CASCADE; +NOTICE: drop cascades to 2 other objects +DETAIL: drop cascades to materialized view ivm_rls +drop cascades to materialized view ivm_rls2 +DROP TABLE num_tbl CASCADE; +DROP USER ivm_user; +DROP USER ivm_admin; +DROP TABLE mv_base_b CASCADE; +NOTICE: drop cascades to 3 other objects +DETAIL: drop cascades to materialized view mv_ivm_1 +drop cascades to view b_view +drop cascades to materialized view b_mview +DROP TABLE mv_base_a CASCADE; diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index 6d8f524ae9..79988e068c 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -86,7 +86,7 @@ test: brin_bloom brin_multi # psql depends on create_am # amutils depends on geometry, create_index_spgist, hash_index, brin # ---------- -test: create_table_like alter_generic alter_operator misc async dbsize misc_functions sysviews tsrf tid tidscan tidrangescan collate.icu.utf8 incremental_sort create_role +test: create_table_like alter_generic alter_operator misc async dbsize misc_functions sysviews tsrf tid tidscan tidrangescan collate.icu.utf8 incremental_sort create_role incremental_matview # collate.*.utf8 tests cannot be run in parallel with each other test: rules psql psql_crosstab amutils stats_ext collate.linux.utf8 diff --git a/src/test/regress/sql/incremental_matview.sql b/src/test/regress/sql/incremental_matview.sql new file mode 100644 index 0000000000..311e9b96fb --- /dev/null +++ b/src/test/regress/sql/incremental_matview.sql @@ -0,0 +1,400 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (i int, j int); +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +CREATE TABLE mv_base_b (i int, k int); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); + +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +REFRESH MATERIALIZED VIEW mv_ivm_1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +DROP MATERIALIZED VIEW mv_ivm_rename; + +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +DROP MATERIALIZED VIEW mv_ivm_unique; + +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +ROLLBACK; + +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +ROLLBACK; + +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +ROLLBACK; + +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +ROLLBACK; + +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +ROLLBACK; + +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +ROLLBACK; + +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +SELECT * FROM mv_self ORDER BY v1; +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; +SELECT * FROM mv_self ORDER BY v1; +ROLLBACK; + +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +SELECT * FROM mv ORDER BY v1; +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; +SELECT * FROM mv ORDER BY v1; +ROLLBACK; + +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +SELECT * FROM mv_ri ORDER BY i1; +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; +ROLLBACK; + +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +-- IMMV containing user defined type +BEGIN; + +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); + +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; + +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); + +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); + +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + +ROLLBACK; + +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; + +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; + +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; + +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; + +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; + +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); + +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; + +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); + +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ROLLBACK; + +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; + +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; + +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; + +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; + +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; + +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; + +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); + +-- base table which has row level security +DROP USER IF EXISTS ivm_admin; +DROP USER IF EXISTS ivm_user; +CREATE USER ivm_admin; +CREATE USER ivm_user; +SET SESSION AUTHORIZATION ivm_admin; + +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'); +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +CREATE POLICY rls_tbl_policy2 ON rls_tbl FOR INSERT TO PUBLIC WITH CHECK(current_user LIKE 'ivm_%'); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; + +SET SESSION AUTHORIZATION ivm_user; + +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; +INSERT INTO rls_tbl VALUES + (3,'baz','ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); + +RESET SESSION AUTHORIZATION; + +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + +DROP TABLE rls_tbl CASCADE; +DROP TABLE num_tbl CASCADE; +DROP USER ivm_user; +DROP USER ivm_admin; + +DROP TABLE mv_base_b CASCADE; +DROP TABLE mv_base_a CASCADE; -- 2.17.1 --Multipart=_Mon__14_Mar_2022_19_12_17_+0900_E9HVp8j5QFkIIek. Content-Type: text/x-diff; name="v26-0008-Add-aggregates-support-in-IVM.patch" Content-Disposition: attachment; filename="v26-0008-Add-aggregates-support-in-IVM.patch" Content-Transfer-Encoding: quoted-printable ^ permalink raw reply [nested|flat] 78+ messages in thread
* [PATCH v24 09/15] Add regression tests for Incremental View Maintenance @ 2021-03-10 02:11 Takuma Hoshiai <[email protected]> 0 siblings, 0 replies; 78+ messages in thread From: Takuma Hoshiai @ 2021-03-10 02:11 UTC (permalink / raw) --- .../regress/expected/incremental_matview.out | 812 ++++++++++++++++++ src/test/regress/parallel_schedule | 2 +- src/test/regress/sql/incremental_matview.sql | 400 +++++++++ 3 files changed, 1213 insertions(+), 1 deletion(-) create mode 100644 src/test/regress/expected/incremental_matview.out create mode 100644 src/test/regress/sql/incremental_matview.sql diff --git a/src/test/regress/expected/incremental_matview.out b/src/test/regress/expected/incremental_matview.out new file mode 100644 index 0000000000..4b14100acd --- /dev/null +++ b/src/test/regress/expected/incremental_matview.out @@ -0,0 +1,812 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (i int, j int); +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +CREATE TABLE mv_base_b (i int, k int); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +NOTICE: could not create an index on materialized view "mv_ivm_1" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ERROR: materialized view "mv_ivm_1" has not been populated +HINT: Use the REFRESH MATERIALIZED VIEW command. +REFRESH MATERIALIZED VIEW mv_ivm_1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_rename_index" on materialized view "mv_ivm_rename" +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +ERROR: IVM column can not be renamed +DROP MATERIALIZED VIEW mv_ivm_rename; +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_unique_index" on materialized view "mv_ivm_unique" +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +ERROR: unique index creation on IVM columns is not supported +DROP MATERIALIZED VIEW mv_ivm_unique; +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +NOTICE: could not create an index on materialized view "mv_ivm_func" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +NOTICE: could not create an index on materialized view "mv_ivm_no_tbl" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_duplicate" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +NOTICE: created index "mv_ivm_distinct_index" on materialized view "mv_ivm_distinct" +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 20 + 30 + 40 + 50 +(6 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +ROLLBACK; +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 120 | 2 | 60.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+---------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 220 | 2 | 110.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 20 | 1 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 120 | 2 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +ROLLBACK; +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 150 | 5 | 30.0000000000000000 +(1 row) + +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 210 | 6 | 35.0000000000000000 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +NOTICE: created index "mv_ivm_avg_bug_index" on materialized view "mv_ivm_avg_bug" +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 3 | 3.3333333333333333 + 2 | 80 | 3 | 26.6666666666666667 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_min_max_index" on materialized view "mv_ivm_min_max" +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 10 + 2 | 20 | 20 + 3 | 30 | 30 + 4 | 40 | 40 + 5 | 50 | 50 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 12 + 2 | 20 | 22 + 3 | 30 | 32 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 11 | 12 + 2 | 20 | 22 + 3 | 30 | 31 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min_max" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 50 +(1 row) + +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 0 | 70 +(1 row) + +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 60 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + | +(1 row) + +ROLLBACK; +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +NOTICE: could not create an index on materialized view "mv_self" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +----+---- + 10 | 10 + 20 | 20 + 30 | 30 +(3 rows) + +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 30 | 30 + 40 | 40 + 200 | 200 +(3 rows) + +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 130 | 130 + 300 | 300 +(4 rows) + +ROLLBACK; +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY v1; + v1 | v2 +----+----- + 10 | 100 + 20 | 200 + 30 | 300 +(3 rows) + +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv ORDER BY v1; + v1 | v2 +------+----- + 10 | 100 + 11 | 100 + 1020 | 200 + 1020 | 222 +(4 rows) + +ROLLBACK; +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +NOTICE: created index "mv_ri_index" on materialized view "mv_ri" +SELECT * FROM mv_ri ORDER BY i1; + i1 | i2 +----+---- + 1 | 1 + 2 | 2 + 3 | 3 +(3 rows) + +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; + i1 | i2 +----+---- + 3 | 3 + 10 | 10 +(2 rows) + +ROLLBACK; +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | +(2 rows) + +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | 20 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i +--- +(0 rows) + +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; + i +--- + 1 + +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 30 + | 3 +(2 rows) + +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 300 + | 30 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 1 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 4 +(1 row) + +ROLLBACK; +-- IMMV containing user defined type +BEGIN; +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: return type mytype is only a shell +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: argument type mytype is only a shell +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +NOTICE: could not create an index on materialized view "mv_mytype" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + x +--- + 1 +(1 row) + +ROLLBACK; +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +ERROR: OUTER JOIN is not supported on incrementally maintainable materialized view +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +ERROR: CTE is not supported on incrementally maintainable materialized view +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +ERROR: ORDER BY clause is not supported on incrementally maintainable materialized view +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; +ERROR: HAVING clause is not supported on incrementally maintainable materialized view +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; +ERROR: mutable function is not supported on incrementally maintainable materialized view +HINT: functions must be marked IMMUTABLE +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; +ERROR: LIMIT/OFFSET clause is not supported on incrementally maintainable materialized view +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; +ERROR: DISTINCT ON is not supported on incrementally maintainable materialized view +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); +ERROR: TABLESAMPLE clause is not supported on incrementally maintainable materialized view +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; +ERROR: window functions are not supported on incrementally maintainable materialized view +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +ERROR: aggregate function with FILTER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +ERROR: aggregate function with DISTINCT arguments is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +ERROR: aggregate function with ORDER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); +ERROR: GROUPING SETS, ROLLUP, or CUBE clauses is not supported on incrementally maintainable materialized view +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ERROR: inheritance parent is not supported on incrementally maintainable materialized view +ROLLBACK; +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; +ERROR: UNION/INTERSECT/EXCEPT statements are not supported on incrementally maintainable materialized view +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; +ERROR: empty target list is not supported on incrementally maintainable materialized view +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; +ERROR: FOR UPDATE/SHARE clause is not supported on incrementally maintainable materialized view +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; +ERROR: column name __ivm_count__ is not supported on incrementally maintainable materialized view +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; +ERROR: GROUP BY expression not appearing in select list is not supported on incrementally maintainable materialized view +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); +ERROR: VALUES is not supported on incrementally maintainable materialized view +-- base table which has row level security +DROP USER IF EXISTS ivm_admin; +NOTICE: role "ivm_admin" does not exist, skipping +DROP USER IF EXISTS ivm_user; +NOTICE: role "ivm_user" does not exist, skipping +CREATE USER ivm_admin; +CREATE USER ivm_user; +SET SESSION AUTHORIZATION ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'); +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +CREATE POLICY rls_tbl_policy2 ON rls_tbl FOR INSERT TO PUBLIC WITH CHECK(current_user LIKE 'ivm_%'); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; +SET SESSION AUTHORIZATION ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +NOTICE: could not create an index on materialized view "ivm_rls" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+---------- + 1 | foo | ivm_user +(1 row) + +INSERT INTO rls_tbl VALUES + (3,'baz','ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+---------- + 1 | foo | ivm_user + 3 | baz | ivm_user +(2 rows) + +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +NOTICE: could not create an index on materialized view "ivm_rls2" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +RESET SESSION AUTHORIZATION; +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +-- +(1 row) + +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + id | data | owner | num +----+-------+----------+--------- + 1 | foo | ivm_user | one + 3 | baz_2 | ivm_user | three_2 +(2 rows) + +DROP TABLE rls_tbl CASCADE; +NOTICE: drop cascades to 2 other objects +DETAIL: drop cascades to materialized view ivm_rls +drop cascades to materialized view ivm_rls2 +DROP TABLE num_tbl CASCADE; +DROP USER ivm_user; +DROP USER ivm_admin; +DROP TABLE mv_base_b CASCADE; +NOTICE: drop cascades to 3 other objects +DETAIL: drop cascades to materialized view mv_ivm_1 +drop cascades to view b_view +drop cascades to materialized view b_mview +DROP TABLE mv_base_a CASCADE; diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index 7be89178f0..b0350f47dd 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -86,7 +86,7 @@ test: brin_bloom brin_multi # ---------- # Another group of parallel tests # ---------- -test: create_table_like alter_generic alter_operator misc async dbsize misc_functions sysviews tsrf tid tidscan tidrangescan collate.icu.utf8 incremental_sort +test: create_table_like alter_generic alter_operator misc async dbsize misc_functions sysviews tsrf tid tidscan tidrangescan collate.icu.utf8 incremental_sort incremental_matview # rules cannot run concurrently with any test that creates # a view or rule in the public schema diff --git a/src/test/regress/sql/incremental_matview.sql b/src/test/regress/sql/incremental_matview.sql new file mode 100644 index 0000000000..311e9b96fb --- /dev/null +++ b/src/test/regress/sql/incremental_matview.sql @@ -0,0 +1,400 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (i int, j int); +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +CREATE TABLE mv_base_b (i int, k int); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); + +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +REFRESH MATERIALIZED VIEW mv_ivm_1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +DROP MATERIALIZED VIEW mv_ivm_rename; + +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +DROP MATERIALIZED VIEW mv_ivm_unique; + +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +ROLLBACK; + +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +ROLLBACK; + +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +ROLLBACK; + +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +ROLLBACK; + +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +ROLLBACK; + +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +ROLLBACK; + +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +SELECT * FROM mv_self ORDER BY v1; +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; +SELECT * FROM mv_self ORDER BY v1; +ROLLBACK; + +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +SELECT * FROM mv ORDER BY v1; +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; +SELECT * FROM mv ORDER BY v1; +ROLLBACK; + +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +SELECT * FROM mv_ri ORDER BY i1; +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; +ROLLBACK; + +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +-- IMMV containing user defined type +BEGIN; + +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); + +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; + +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); + +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); + +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + +ROLLBACK; + +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; + +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; + +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; + +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; + +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; + +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); + +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; + +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); + +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ROLLBACK; + +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; + +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; + +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; + +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; + +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; + +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; + +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); + +-- base table which has row level security +DROP USER IF EXISTS ivm_admin; +DROP USER IF EXISTS ivm_user; +CREATE USER ivm_admin; +CREATE USER ivm_user; +SET SESSION AUTHORIZATION ivm_admin; + +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'); +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +CREATE POLICY rls_tbl_policy2 ON rls_tbl FOR INSERT TO PUBLIC WITH CHECK(current_user LIKE 'ivm_%'); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; + +SET SESSION AUTHORIZATION ivm_user; + +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; +INSERT INTO rls_tbl VALUES + (3,'baz','ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); + +RESET SESSION AUTHORIZATION; + +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + +DROP TABLE rls_tbl CASCADE; +DROP TABLE num_tbl CASCADE; +DROP USER ivm_user; +DROP USER ivm_admin; + +DROP TABLE mv_base_b CASCADE; +DROP TABLE mv_base_a CASCADE; -- 2.17.1 --Multipart=_Fri__29_Oct_2021_18_16_28_+0900_jlYRKjywLqhZ7oyk Content-Type: text/x-diff; name="v24-0010-Add-documentations-about-Incremental-View-Mainte.patch" Content-Disposition: attachment; filename="v24-0010-Add-documentations-about-Incremental-View-Mainte.patch" Content-Transfer-Encoding: 7bit ^ permalink raw reply [nested|flat] 78+ messages in thread
* [PATCH v34 10/11] Add regression tests for Incremental View Maintenance @ 2021-03-10 02:11 Takuma Hoshiai <[email protected]> 0 siblings, 0 replies; 78+ messages in thread From: Takuma Hoshiai @ 2021-03-10 02:11 UTC (permalink / raw) --- .../regress/expected/incremental_matview.out | 1030 +++++++++++++++++ src/test/regress/parallel_schedule | 2 +- src/test/regress/sql/incremental_matview.sql | 533 +++++++++ 3 files changed, 1564 insertions(+), 1 deletion(-) create mode 100644 src/test/regress/expected/incremental_matview.out create mode 100644 src/test/regress/sql/incremental_matview.sql diff --git a/src/test/regress/expected/incremental_matview.out b/src/test/regress/expected/incremental_matview.out new file mode 100644 index 0000000000..d65896425e --- /dev/null +++ b/src/test/regress/expected/incremental_matview.out @@ -0,0 +1,1030 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (i int, j int); +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +CREATE TABLE mv_base_b (i int, k int); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ERROR: materialized view "mv_ivm_1" has not been populated +HINT: Use the REFRESH MATERIALIZED VIEW command. +REFRESH MATERIALIZED VIEW mv_ivm_1; +NOTICE: could not create an index on materialized view "mv_ivm_1" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 17 +(1 row) + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 1 +(1 row) + +ROLLBACK; +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_rename_index" on materialized view "mv_ivm_rename" +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +ERROR: IVM column can not be renamed +DROP MATERIALIZED VIEW mv_ivm_rename; +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_unique_index" on materialized view "mv_ivm_unique" +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +ERROR: unique index creation on IVM columns is not supported +DROP MATERIALIZED VIEW mv_ivm_unique; +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +NOTICE: could not create an index on materialized view "mv_ivm_func" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +NOTICE: could not create an index on materialized view "mv_ivm_no_tbl" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_duplicate" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +NOTICE: created index "mv_ivm_distinct_index" on materialized view "mv_ivm_distinct" +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 20 + 30 + 40 + 50 +(6 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +ROLLBACK; +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 120 | 2 | 60.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+---------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 220 | 2 | 110.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 20 | 1 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 120 | 2 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; + sum | count +-----+------- +(0 rows) + +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; + i | sum | count +---+-----+------- +(0 rows) + +ROLLBACK; +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 150 | 5 | 30.0000000000000000 +(1 row) + +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 210 | 6 | 35.0000000000000000 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +NOTICE: created index "mv_ivm_avg_bug_index" on materialized view "mv_ivm_avg_bug" +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 3 | 3.3333333333333333 + 2 | 80 | 3 | 26.6666666666666667 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_min_max_index" on materialized view "mv_ivm_min_max" +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 10 + 2 | 20 | 20 + 3 | 30 | 30 + 4 | 40 | 40 + 5 | 50 | 50 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 12 + 2 | 20 | 22 + 3 | 30 | 32 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 11 | 12 + 2 | 20 | 22 + 3 | 30 | 31 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min_max" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 50 +(1 row) + +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 0 | 70 +(1 row) + +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 60 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + | +(1 row) + +ROLLBACK; +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min; + min +----- + 10 +(1 row) + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + min +----- + 20 +(1 row) + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; + min +----- + 30 +(1 row) + +ROLLBACK; +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | sum +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | b +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ERROR: too many column names were specified +ROLLBACK; +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +NOTICE: could not create an index on materialized view "mv_self" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +----+---- + 10 | 10 + 20 | 20 + 30 | 30 +(3 rows) + +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 30 | 30 + 40 | 40 + 200 | 200 +(3 rows) + +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 130 | 130 + 300 | 300 +(4 rows) + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 70 | 70 + 70 | 77 + 77 | 70 + 77 | 77 + 130 | 130 + 300 | 300 +(8 rows) + +ROLLBACK; +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY v1; + v1 | v2 +----+----- + 10 | 100 + 20 | 200 + 30 | 300 +(3 rows) + +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv ORDER BY v1; + v1 | v2 +------+----- + 10 | 100 + 11 | 100 + 1020 | 200 + 1020 | 222 +(4 rows) + +ROLLBACK; +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +NOTICE: created index "mv_ri_index" on materialized view "mv_ri" +SELECT * FROM mv_ri ORDER BY i1; + i1 | i2 +----+---- + 1 | 1 + 2 | 2 + 3 | 3 +(3 rows) + +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; + i1 | i2 +----+---- + 3 | 3 + 10 | 10 +(2 rows) + +ROLLBACK; +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | +(2 rows) + +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | 20 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i +--- +(0 rows) + +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; + i +--- + 1 + +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 30 + | 3 +(2 rows) + +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 300 + | 30 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 1 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 4 +(1 row) + +ROLLBACK; +-- IMMV containing user defined type +BEGIN; +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: return type mytype is only a shell +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: argument type mytype is only a shell +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +NOTICE: could not create an index on materialized view "mv_mytype" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + x +--- + 1 +(1 row) + +ROLLBACK; +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +ERROR: OUTER JOIN is not supported on incrementally maintainable materialized view +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +ERROR: CTE is not supported on incrementally maintainable materialized view +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +ERROR: ORDER BY clause is not supported on incrementally maintainable materialized view +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; +ERROR: HAVING clause is not supported on incrementally maintainable materialized view +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; +ERROR: mutable function is not supported on incrementally maintainable materialized view +HINT: functions must be marked IMMUTABLE +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; +ERROR: LIMIT/OFFSET clause is not supported on incrementally maintainable materialized view +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; +ERROR: DISTINCT ON is not supported on incrementally maintainable materialized view +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); +ERROR: TABLESAMPLE clause is not supported on incrementally maintainable materialized view +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; +ERROR: window functions are not supported on incrementally maintainable materialized view +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +ERROR: aggregate function with FILTER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +ERROR: aggregate function with DISTINCT arguments is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +ERROR: aggregate function with ORDER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); +ERROR: GROUPING SETS, ROLLUP, or CUBE clauses is not supported on incrementally maintainable materialized view +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ERROR: inheritance parent is not supported on incrementally maintainable materialized view +ROLLBACK; +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; +ERROR: UNION/INTERSECT/EXCEPT statements are not supported on incrementally maintainable materialized view +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; +ERROR: empty target list is not supported on incrementally maintainable materialized view +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; +ERROR: FOR UPDATE/SHARE clause is not supported on incrementally maintainable materialized view +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; +ERROR: column name __ivm_count__ is not supported on incrementally maintainable materialized view +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; +ERROR: GROUP BY expression not appearing in select list is not supported on incrementally maintainable materialized view +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); +ERROR: VALUES is not supported on incrementally maintainable materialized view +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +NOTICE: role "regress_ivm_admin" does not exist, skipping +DROP USER IF EXISTS regress_ivm_user; +NOTICE: role "regress_ivm_user" does not exist, skipping +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +NOTICE: could not create an index on materialized view "ivm_rls" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user +(1 row) + +RESET SESSION AUTHORIZATION; +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user + 3 | baz | regress_ivm_user +(2 rows) + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +-- +(1 row) + +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+-------+------------------ + 2 | bar | regress_ivm_user + 3 | baz | regress_ivm_user + 6 | corge | regress_ivm_user +(3 rows) + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +NOTICE: could not create an index on materialized view "ivm_rls2" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +RESET SESSION AUTHORIZATION; +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +-- +(1 row) + +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + id | data | owner | num +----+-------+------------------+--------- + 2 | bar | regress_ivm_user | two + 3 | baz_2 | regress_ivm_user | three_2 + 6 | corge | regress_ivm_user | six +(3 rows) + +-- automatic index creation +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; +NOTICE: created index "mv_idx1_index" on materialized view "mv_idx1" +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; +NOTICE: created index "mv_idx2_index" on materialized view "mv_idx2" +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; +NOTICE: created index "mv_idx3_index" on materialized view "mv_idx3" +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +NOTICE: could not create an index on materialized view "mv_idx4" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; +NOTICE: could not create an index on materialized view "mv_idx5" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +-- cleanup +DROP TABLE rls_tbl CASCADE; +NOTICE: drop cascades to 2 other objects +DETAIL: drop cascades to materialized view ivm_rls +drop cascades to materialized view ivm_rls2 +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; +DROP TABLE mv_base_b CASCADE; +NOTICE: drop cascades to 3 other objects +DETAIL: drop cascades to materialized view mv_ivm_1 +drop cascades to view b_view +drop cascades to materialized view b_mview +DROP TABLE mv_base_a CASCADE; diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index 2429ec2bba..03814f34e9 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -78,7 +78,7 @@ test: brin_bloom brin_multi # psql depends on create_am # amutils depends on geometry, create_index_spgist, hash_index, brin # ---------- -test: create_table_like alter_generic alter_operator misc async dbsize merge misc_functions sysviews tsrf tid tidscan tidrangescan collate.utf8 collate.icu.utf8 incremental_sort create_role +test: create_table_like alter_generic alter_operator misc async dbsize merge misc_functions sysviews tsrf tid tidscan tidrangescan collate.utf8 collate.icu.utf8 incremental_sort create_role incremental_matview # collate.linux.utf8 and collate.icu.utf8 tests cannot be run in parallel with each other test: rules psql psql_crosstab amutils stats_ext collate.linux.utf8 collate.windows.win1252 diff --git a/src/test/regress/sql/incremental_matview.sql b/src/test/regress/sql/incremental_matview.sql new file mode 100644 index 0000000000..90116edff8 --- /dev/null +++ b/src/test/regress/sql/incremental_matview.sql @@ -0,0 +1,533 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (i int, j int); +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +CREATE TABLE mv_base_b (i int, k int); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); + +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +REFRESH MATERIALIZED VIEW mv_ivm_1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; + +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; +ROLLBACK; + +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +DROP MATERIALIZED VIEW mv_ivm_rename; + +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +DROP MATERIALIZED VIEW mv_ivm_unique; + +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +ROLLBACK; + +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +ROLLBACK; + +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +ROLLBACK; + +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +ROLLBACK; + +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +ROLLBACK; + +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min; + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); + +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; +ROLLBACK; + +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +SELECT * FROM mv_self ORDER BY v1; +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; +SELECT * FROM mv_self ORDER BY v1; + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + +ROLLBACK; + +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +SELECT * FROM mv ORDER BY v1; +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; +SELECT * FROM mv ORDER BY v1; +ROLLBACK; + +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +SELECT * FROM mv_ri ORDER BY i1; +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; +ROLLBACK; + +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +-- IMMV containing user defined type +BEGIN; + +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); + +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; + +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); + +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); + +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + +ROLLBACK; + +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; + +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; + +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; + +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; + +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; + +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); + +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; + +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); + +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ROLLBACK; + +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; + +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; + +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; + +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; + +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; + +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; + +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); + +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +DROP USER IF EXISTS regress_ivm_user; +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; + +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); + +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; + +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; + +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; +RESET SESSION AUTHORIZATION; + +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +RESET SESSION AUTHORIZATION; + +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + +-- automatic index creation +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); + +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; + +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; + +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; + +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; + +-- cleanup + +DROP TABLE rls_tbl CASCADE; +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; + +DROP TABLE mv_base_b CASCADE; +DROP TABLE mv_base_a CASCADE; -- 2.34.1 --Multipart=_Thu__11_Jul_2024_13_23_57_+0900_hKsU2G3a3BgS2FFs Content-Type: text/x-diff; name="v34-0009-Add-support-for-min-max-aggregates-for-IVM.patch" Content-Disposition: attachment; filename="v34-0009-Add-support-for-min-max-aggregates-for-IVM.patch" Content-Transfer-Encoding: 7bit ^ permalink raw reply [nested|flat] 78+ messages in thread
* [PATCH v25 09/15] Add regression tests for Incremental View Maintenance @ 2021-03-10 02:11 Takuma Hoshiai <[email protected]> 0 siblings, 0 replies; 78+ messages in thread From: Takuma Hoshiai @ 2021-03-10 02:11 UTC (permalink / raw) --- .../regress/expected/incremental_matview.out | 812 ++++++++++++++++++ src/test/regress/parallel_schedule | 2 +- src/test/regress/sql/incremental_matview.sql | 400 +++++++++ 3 files changed, 1213 insertions(+), 1 deletion(-) create mode 100644 src/test/regress/expected/incremental_matview.out create mode 100644 src/test/regress/sql/incremental_matview.sql diff --git a/src/test/regress/expected/incremental_matview.out b/src/test/regress/expected/incremental_matview.out new file mode 100644 index 0000000000..7b10fcddbe --- /dev/null +++ b/src/test/regress/expected/incremental_matview.out @@ -0,0 +1,812 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (i int, j int); +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +CREATE TABLE mv_base_b (i int, k int); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ERROR: materialized view "mv_ivm_1" has not been populated +HINT: Use the REFRESH MATERIALIZED VIEW command. +REFRESH MATERIALIZED VIEW mv_ivm_1; +NOTICE: could not create an index on materialized view "mv_ivm_1" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_rename_index" on materialized view "mv_ivm_rename" +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +ERROR: IVM column can not be renamed +DROP MATERIALIZED VIEW mv_ivm_rename; +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_unique_index" on materialized view "mv_ivm_unique" +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +ERROR: unique index creation on IVM columns is not supported +DROP MATERIALIZED VIEW mv_ivm_unique; +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +NOTICE: could not create an index on materialized view "mv_ivm_func" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +NOTICE: could not create an index on materialized view "mv_ivm_no_tbl" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_duplicate" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +NOTICE: created index "mv_ivm_distinct_index" on materialized view "mv_ivm_distinct" +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 20 + 30 + 40 + 50 +(6 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +ROLLBACK; +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 120 | 2 | 60.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+---------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 220 | 2 | 110.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 20 | 1 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 120 | 2 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +ROLLBACK; +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 150 | 5 | 30.0000000000000000 +(1 row) + +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 210 | 6 | 35.0000000000000000 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +NOTICE: created index "mv_ivm_avg_bug_index" on materialized view "mv_ivm_avg_bug" +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 3 | 3.3333333333333333 + 2 | 80 | 3 | 26.6666666666666667 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_min_max_index" on materialized view "mv_ivm_min_max" +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 10 + 2 | 20 | 20 + 3 | 30 | 30 + 4 | 40 | 40 + 5 | 50 | 50 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 12 + 2 | 20 | 22 + 3 | 30 | 32 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 11 | 12 + 2 | 20 | 22 + 3 | 30 | 31 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min_max" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 50 +(1 row) + +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 0 | 70 +(1 row) + +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 60 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + | +(1 row) + +ROLLBACK; +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +NOTICE: could not create an index on materialized view "mv_self" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +----+---- + 10 | 10 + 20 | 20 + 30 | 30 +(3 rows) + +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 30 | 30 + 40 | 40 + 200 | 200 +(3 rows) + +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 130 | 130 + 300 | 300 +(4 rows) + +ROLLBACK; +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY v1; + v1 | v2 +----+----- + 10 | 100 + 20 | 200 + 30 | 300 +(3 rows) + +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv ORDER BY v1; + v1 | v2 +------+----- + 10 | 100 + 11 | 100 + 1020 | 200 + 1020 | 222 +(4 rows) + +ROLLBACK; +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +NOTICE: created index "mv_ri_index" on materialized view "mv_ri" +SELECT * FROM mv_ri ORDER BY i1; + i1 | i2 +----+---- + 1 | 1 + 2 | 2 + 3 | 3 +(3 rows) + +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; + i1 | i2 +----+---- + 3 | 3 + 10 | 10 +(2 rows) + +ROLLBACK; +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | +(2 rows) + +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | 20 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i +--- +(0 rows) + +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; + i +--- + 1 + +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 30 + | 3 +(2 rows) + +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 300 + | 30 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 1 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 4 +(1 row) + +ROLLBACK; +-- IMMV containing user defined type +BEGIN; +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: return type mytype is only a shell +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: argument type mytype is only a shell +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +NOTICE: could not create an index on materialized view "mv_mytype" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + x +--- + 1 +(1 row) + +ROLLBACK; +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +ERROR: OUTER JOIN is not supported on incrementally maintainable materialized view +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +ERROR: CTE is not supported on incrementally maintainable materialized view +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +ERROR: ORDER BY clause is not supported on incrementally maintainable materialized view +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; +ERROR: HAVING clause is not supported on incrementally maintainable materialized view +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; +ERROR: mutable function is not supported on incrementally maintainable materialized view +HINT: functions must be marked IMMUTABLE +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; +ERROR: LIMIT/OFFSET clause is not supported on incrementally maintainable materialized view +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; +ERROR: DISTINCT ON is not supported on incrementally maintainable materialized view +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); +ERROR: TABLESAMPLE clause is not supported on incrementally maintainable materialized view +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; +ERROR: window functions are not supported on incrementally maintainable materialized view +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +ERROR: aggregate function with FILTER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +ERROR: aggregate function with DISTINCT arguments is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +ERROR: aggregate function with ORDER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); +ERROR: GROUPING SETS, ROLLUP, or CUBE clauses is not supported on incrementally maintainable materialized view +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ERROR: inheritance parent is not supported on incrementally maintainable materialized view +ROLLBACK; +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; +ERROR: UNION/INTERSECT/EXCEPT statements are not supported on incrementally maintainable materialized view +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; +ERROR: empty target list is not supported on incrementally maintainable materialized view +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; +ERROR: FOR UPDATE/SHARE clause is not supported on incrementally maintainable materialized view +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; +ERROR: column name __ivm_count__ is not supported on incrementally maintainable materialized view +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; +ERROR: GROUP BY expression not appearing in select list is not supported on incrementally maintainable materialized view +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); +ERROR: VALUES is not supported on incrementally maintainable materialized view +-- base table which has row level security +DROP USER IF EXISTS ivm_admin; +NOTICE: role "ivm_admin" does not exist, skipping +DROP USER IF EXISTS ivm_user; +NOTICE: role "ivm_user" does not exist, skipping +CREATE USER ivm_admin; +CREATE USER ivm_user; +SET SESSION AUTHORIZATION ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'); +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +CREATE POLICY rls_tbl_policy2 ON rls_tbl FOR INSERT TO PUBLIC WITH CHECK(current_user LIKE 'ivm_%'); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; +SET SESSION AUTHORIZATION ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +NOTICE: could not create an index on materialized view "ivm_rls" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+---------- + 1 | foo | ivm_user +(1 row) + +INSERT INTO rls_tbl VALUES + (3,'baz','ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+---------- + 1 | foo | ivm_user + 3 | baz | ivm_user +(2 rows) + +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +NOTICE: could not create an index on materialized view "ivm_rls2" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +RESET SESSION AUTHORIZATION; +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +-- +(1 row) + +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + id | data | owner | num +----+-------+----------+--------- + 1 | foo | ivm_user | one + 3 | baz_2 | ivm_user | three_2 +(2 rows) + +DROP TABLE rls_tbl CASCADE; +NOTICE: drop cascades to 2 other objects +DETAIL: drop cascades to materialized view ivm_rls +drop cascades to materialized view ivm_rls2 +DROP TABLE num_tbl CASCADE; +DROP USER ivm_user; +DROP USER ivm_admin; +DROP TABLE mv_base_b CASCADE; +NOTICE: drop cascades to 3 other objects +DETAIL: drop cascades to materialized view mv_ivm_1 +drop cascades to view b_view +drop cascades to materialized view b_mview +DROP TABLE mv_base_a CASCADE; diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index 861c30a73a..a838d176dd 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -89,7 +89,7 @@ test: brin_bloom brin_multi # ---------- # Another group of parallel tests # ---------- -test: create_table_like alter_generic alter_operator misc async dbsize misc_functions sysviews tsrf tid tidscan tidrangescan collate.icu.utf8 incremental_sort create_role +test: create_table_like alter_generic alter_operator misc async dbsize misc_functions sysviews tsrf tid tidscan tidrangescan collate.icu.utf8 incremental_sort create_role incremental_matview # rules cannot run concurrently with any test that creates # a view or rule in the public schema diff --git a/src/test/regress/sql/incremental_matview.sql b/src/test/regress/sql/incremental_matview.sql new file mode 100644 index 0000000000..311e9b96fb --- /dev/null +++ b/src/test/regress/sql/incremental_matview.sql @@ -0,0 +1,400 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (i int, j int); +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +CREATE TABLE mv_base_b (i int, k int); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); + +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +REFRESH MATERIALIZED VIEW mv_ivm_1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +DROP MATERIALIZED VIEW mv_ivm_rename; + +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +DROP MATERIALIZED VIEW mv_ivm_unique; + +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +ROLLBACK; + +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +ROLLBACK; + +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +ROLLBACK; + +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +ROLLBACK; + +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +ROLLBACK; + +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +ROLLBACK; + +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +SELECT * FROM mv_self ORDER BY v1; +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; +SELECT * FROM mv_self ORDER BY v1; +ROLLBACK; + +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +SELECT * FROM mv ORDER BY v1; +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; +SELECT * FROM mv ORDER BY v1; +ROLLBACK; + +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +SELECT * FROM mv_ri ORDER BY i1; +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; +ROLLBACK; + +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +-- IMMV containing user defined type +BEGIN; + +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); + +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; + +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); + +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); + +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + +ROLLBACK; + +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; + +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; + +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; + +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; + +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; + +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); + +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; + +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); + +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ROLLBACK; + +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; + +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; + +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; + +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; + +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; + +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; + +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); + +-- base table which has row level security +DROP USER IF EXISTS ivm_admin; +DROP USER IF EXISTS ivm_user; +CREATE USER ivm_admin; +CREATE USER ivm_user; +SET SESSION AUTHORIZATION ivm_admin; + +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'); +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +CREATE POLICY rls_tbl_policy2 ON rls_tbl FOR INSERT TO PUBLIC WITH CHECK(current_user LIKE 'ivm_%'); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; + +SET SESSION AUTHORIZATION ivm_user; + +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; +INSERT INTO rls_tbl VALUES + (3,'baz','ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); + +RESET SESSION AUTHORIZATION; + +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + +DROP TABLE rls_tbl CASCADE; +DROP TABLE num_tbl CASCADE; +DROP USER ivm_user; +DROP USER ivm_admin; + +DROP TABLE mv_base_b CASCADE; +DROP TABLE mv_base_a CASCADE; -- 2.17.1 --Multipart=_Fri__4_Feb_2022_01_48_06_+0900_N8BNZpfOR27sWrgY Content-Type: text/x-diff; name="v25-0008-Add-aggregates-support-in-IVM.patch" Content-Disposition: attachment; filename="v25-0008-Add-aggregates-support-in-IVM.patch" Content-Transfer-Encoding: quoted-printable ^ permalink raw reply [nested|flat] 78+ messages in thread
* [PATCH v32 10/11] Add regression tests for Incremental View Maintenance @ 2021-03-10 02:11 Takuma Hoshiai <[email protected]> 0 siblings, 0 replies; 78+ messages in thread From: Takuma Hoshiai @ 2021-03-10 02:11 UTC (permalink / raw) --- .../regress/expected/incremental_matview.out | 1030 +++++++++++++++++ src/test/regress/parallel_schedule | 2 +- src/test/regress/sql/incremental_matview.sql | 533 +++++++++ 3 files changed, 1564 insertions(+), 1 deletion(-) create mode 100644 src/test/regress/expected/incremental_matview.out create mode 100644 src/test/regress/sql/incremental_matview.sql diff --git a/src/test/regress/expected/incremental_matview.out b/src/test/regress/expected/incremental_matview.out new file mode 100644 index 0000000000..d65896425e --- /dev/null +++ b/src/test/regress/expected/incremental_matview.out @@ -0,0 +1,1030 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (i int, j int); +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +CREATE TABLE mv_base_b (i int, k int); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ERROR: materialized view "mv_ivm_1" has not been populated +HINT: Use the REFRESH MATERIALIZED VIEW command. +REFRESH MATERIALIZED VIEW mv_ivm_1; +NOTICE: could not create an index on materialized view "mv_ivm_1" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 17 +(1 row) + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 1 +(1 row) + +ROLLBACK; +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_rename_index" on materialized view "mv_ivm_rename" +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +ERROR: IVM column can not be renamed +DROP MATERIALIZED VIEW mv_ivm_rename; +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_unique_index" on materialized view "mv_ivm_unique" +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +ERROR: unique index creation on IVM columns is not supported +DROP MATERIALIZED VIEW mv_ivm_unique; +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +NOTICE: could not create an index on materialized view "mv_ivm_func" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +NOTICE: could not create an index on materialized view "mv_ivm_no_tbl" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_duplicate" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +NOTICE: created index "mv_ivm_distinct_index" on materialized view "mv_ivm_distinct" +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 20 + 30 + 40 + 50 +(6 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +ROLLBACK; +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 120 | 2 | 60.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+---------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 220 | 2 | 110.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 20 | 1 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 120 | 2 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; + sum | count +-----+------- +(0 rows) + +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; + i | sum | count +---+-----+------- +(0 rows) + +ROLLBACK; +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 150 | 5 | 30.0000000000000000 +(1 row) + +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 210 | 6 | 35.0000000000000000 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +NOTICE: created index "mv_ivm_avg_bug_index" on materialized view "mv_ivm_avg_bug" +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 3 | 3.3333333333333333 + 2 | 80 | 3 | 26.6666666666666667 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_min_max_index" on materialized view "mv_ivm_min_max" +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 10 + 2 | 20 | 20 + 3 | 30 | 30 + 4 | 40 | 40 + 5 | 50 | 50 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 12 + 2 | 20 | 22 + 3 | 30 | 32 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 11 | 12 + 2 | 20 | 22 + 3 | 30 | 31 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min_max" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 50 +(1 row) + +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 0 | 70 +(1 row) + +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 60 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + | +(1 row) + +ROLLBACK; +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min; + min +----- + 10 +(1 row) + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + min +----- + 20 +(1 row) + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; + min +----- + 30 +(1 row) + +ROLLBACK; +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | sum +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | b +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ERROR: too many column names were specified +ROLLBACK; +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +NOTICE: could not create an index on materialized view "mv_self" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +----+---- + 10 | 10 + 20 | 20 + 30 | 30 +(3 rows) + +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 30 | 30 + 40 | 40 + 200 | 200 +(3 rows) + +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 130 | 130 + 300 | 300 +(4 rows) + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 70 | 70 + 70 | 77 + 77 | 70 + 77 | 77 + 130 | 130 + 300 | 300 +(8 rows) + +ROLLBACK; +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY v1; + v1 | v2 +----+----- + 10 | 100 + 20 | 200 + 30 | 300 +(3 rows) + +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv ORDER BY v1; + v1 | v2 +------+----- + 10 | 100 + 11 | 100 + 1020 | 200 + 1020 | 222 +(4 rows) + +ROLLBACK; +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +NOTICE: created index "mv_ri_index" on materialized view "mv_ri" +SELECT * FROM mv_ri ORDER BY i1; + i1 | i2 +----+---- + 1 | 1 + 2 | 2 + 3 | 3 +(3 rows) + +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; + i1 | i2 +----+---- + 3 | 3 + 10 | 10 +(2 rows) + +ROLLBACK; +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | +(2 rows) + +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | 20 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i +--- +(0 rows) + +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; + i +--- + 1 + +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 30 + | 3 +(2 rows) + +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 300 + | 30 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 1 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 4 +(1 row) + +ROLLBACK; +-- IMMV containing user defined type +BEGIN; +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: return type mytype is only a shell +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: argument type mytype is only a shell +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +NOTICE: could not create an index on materialized view "mv_mytype" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + x +--- + 1 +(1 row) + +ROLLBACK; +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +ERROR: OUTER JOIN is not supported on incrementally maintainable materialized view +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +ERROR: CTE is not supported on incrementally maintainable materialized view +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +ERROR: ORDER BY clause is not supported on incrementally maintainable materialized view +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; +ERROR: HAVING clause is not supported on incrementally maintainable materialized view +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; +ERROR: mutable function is not supported on incrementally maintainable materialized view +HINT: functions must be marked IMMUTABLE +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; +ERROR: LIMIT/OFFSET clause is not supported on incrementally maintainable materialized view +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; +ERROR: DISTINCT ON is not supported on incrementally maintainable materialized view +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); +ERROR: TABLESAMPLE clause is not supported on incrementally maintainable materialized view +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; +ERROR: window functions are not supported on incrementally maintainable materialized view +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +ERROR: aggregate function with FILTER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +ERROR: aggregate function with DISTINCT arguments is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +ERROR: aggregate function with ORDER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); +ERROR: GROUPING SETS, ROLLUP, or CUBE clauses is not supported on incrementally maintainable materialized view +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ERROR: inheritance parent is not supported on incrementally maintainable materialized view +ROLLBACK; +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; +ERROR: UNION/INTERSECT/EXCEPT statements are not supported on incrementally maintainable materialized view +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; +ERROR: empty target list is not supported on incrementally maintainable materialized view +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; +ERROR: FOR UPDATE/SHARE clause is not supported on incrementally maintainable materialized view +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; +ERROR: column name __ivm_count__ is not supported on incrementally maintainable materialized view +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; +ERROR: GROUP BY expression not appearing in select list is not supported on incrementally maintainable materialized view +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); +ERROR: VALUES is not supported on incrementally maintainable materialized view +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +NOTICE: role "regress_ivm_admin" does not exist, skipping +DROP USER IF EXISTS regress_ivm_user; +NOTICE: role "regress_ivm_user" does not exist, skipping +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +NOTICE: could not create an index on materialized view "ivm_rls" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user +(1 row) + +RESET SESSION AUTHORIZATION; +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user + 3 | baz | regress_ivm_user +(2 rows) + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +-- +(1 row) + +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+-------+------------------ + 2 | bar | regress_ivm_user + 3 | baz | regress_ivm_user + 6 | corge | regress_ivm_user +(3 rows) + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +NOTICE: could not create an index on materialized view "ivm_rls2" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +RESET SESSION AUTHORIZATION; +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +-- +(1 row) + +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + id | data | owner | num +----+-------+------------------+--------- + 2 | bar | regress_ivm_user | two + 3 | baz_2 | regress_ivm_user | three_2 + 6 | corge | regress_ivm_user | six +(3 rows) + +-- automatic index creation +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; +NOTICE: created index "mv_idx1_index" on materialized view "mv_idx1" +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; +NOTICE: created index "mv_idx2_index" on materialized view "mv_idx2" +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; +NOTICE: created index "mv_idx3_index" on materialized view "mv_idx3" +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +NOTICE: could not create an index on materialized view "mv_idx4" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; +NOTICE: could not create an index on materialized view "mv_idx5" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +-- cleanup +DROP TABLE rls_tbl CASCADE; +NOTICE: drop cascades to 2 other objects +DETAIL: drop cascades to materialized view ivm_rls +drop cascades to materialized view ivm_rls2 +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; +DROP TABLE mv_base_b CASCADE; +NOTICE: drop cascades to 3 other objects +DETAIL: drop cascades to materialized view mv_ivm_1 +drop cascades to view b_view +drop cascades to materialized view b_mview +DROP TABLE mv_base_a CASCADE; diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index 5ac6e871f5..64c910af65 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -78,7 +78,7 @@ test: brin_bloom brin_multi # psql depends on create_am # amutils depends on geometry, create_index_spgist, hash_index, brin # ---------- -test: create_table_like alter_generic alter_operator misc async dbsize merge misc_functions sysviews tsrf tid tidscan tidrangescan collate.utf8 collate.icu.utf8 incremental_sort create_role without_overlaps +test: create_table_like alter_generic alter_operator misc async dbsize merge misc_functions sysviews tsrf tid tidscan tidrangescan collate.utf8 collate.icu.utf8 incremental_sort create_role without_overlaps incremental_matview # collate.linux.utf8 and collate.icu.utf8 tests cannot be run in parallel with each other test: rules psql psql_crosstab amutils stats_ext collate.linux.utf8 collate.windows.win1252 diff --git a/src/test/regress/sql/incremental_matview.sql b/src/test/regress/sql/incremental_matview.sql new file mode 100644 index 0000000000..90116edff8 --- /dev/null +++ b/src/test/regress/sql/incremental_matview.sql @@ -0,0 +1,533 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (i int, j int); +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +CREATE TABLE mv_base_b (i int, k int); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); + +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +REFRESH MATERIALIZED VIEW mv_ivm_1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; + +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; +ROLLBACK; + +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +DROP MATERIALIZED VIEW mv_ivm_rename; + +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +DROP MATERIALIZED VIEW mv_ivm_unique; + +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +ROLLBACK; + +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +ROLLBACK; + +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +ROLLBACK; + +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +ROLLBACK; + +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +ROLLBACK; + +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min; + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); + +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; +ROLLBACK; + +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +SELECT * FROM mv_self ORDER BY v1; +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; +SELECT * FROM mv_self ORDER BY v1; + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + +ROLLBACK; + +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +SELECT * FROM mv ORDER BY v1; +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; +SELECT * FROM mv ORDER BY v1; +ROLLBACK; + +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +SELECT * FROM mv_ri ORDER BY i1; +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; +ROLLBACK; + +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +-- IMMV containing user defined type +BEGIN; + +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); + +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; + +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); + +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); + +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + +ROLLBACK; + +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; + +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; + +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; + +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; + +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; + +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); + +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; + +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); + +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ROLLBACK; + +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; + +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; + +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; + +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; + +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; + +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; + +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); + +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +DROP USER IF EXISTS regress_ivm_user; +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; + +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); + +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; + +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; + +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; +RESET SESSION AUTHORIZATION; + +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +RESET SESSION AUTHORIZATION; + +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + +-- automatic index creation +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); + +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; + +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; + +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; + +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; + +-- cleanup + +DROP TABLE rls_tbl CASCADE; +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; + +DROP TABLE mv_base_b CASCADE; +DROP TABLE mv_base_a CASCADE; -- 2.25.1 --Multipart=_Sun__31_Mar_2024_22_59_31_+0900_msknEviJj08_wgqO Content-Type: text/x-diff; name="v32-0011-Add-documentations-about-Incremental-View-Mainte.patch" Content-Disposition: attachment; filename="v32-0011-Add-documentations-about-Incremental-View-Mainte.patch" Content-Transfer-Encoding: 7bit ^ permalink raw reply [nested|flat] 78+ messages in thread
* [PATCH v33 10/11] Add regression tests for Incremental View Maintenance @ 2021-03-10 02:11 Takuma Hoshiai <[email protected]> 0 siblings, 0 replies; 78+ messages in thread From: Takuma Hoshiai @ 2021-03-10 02:11 UTC (permalink / raw) --- .../regress/expected/incremental_matview.out | 1030 +++++++++++++++++ src/test/regress/parallel_schedule | 2 +- src/test/regress/sql/incremental_matview.sql | 533 +++++++++ 3 files changed, 1564 insertions(+), 1 deletion(-) create mode 100644 src/test/regress/expected/incremental_matview.out create mode 100644 src/test/regress/sql/incremental_matview.sql diff --git a/src/test/regress/expected/incremental_matview.out b/src/test/regress/expected/incremental_matview.out new file mode 100644 index 0000000000..d65896425e --- /dev/null +++ b/src/test/regress/expected/incremental_matview.out @@ -0,0 +1,1030 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (i int, j int); +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +CREATE TABLE mv_base_b (i int, k int); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ERROR: materialized view "mv_ivm_1" has not been populated +HINT: Use the REFRESH MATERIALIZED VIEW command. +REFRESH MATERIALIZED VIEW mv_ivm_1; +NOTICE: could not create an index on materialized view "mv_ivm_1" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 17 +(1 row) + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 1 +(1 row) + +ROLLBACK; +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_rename_index" on materialized view "mv_ivm_rename" +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +ERROR: IVM column can not be renamed +DROP MATERIALIZED VIEW mv_ivm_rename; +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_unique_index" on materialized view "mv_ivm_unique" +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +ERROR: unique index creation on IVM columns is not supported +DROP MATERIALIZED VIEW mv_ivm_unique; +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +NOTICE: could not create an index on materialized view "mv_ivm_func" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +NOTICE: could not create an index on materialized view "mv_ivm_no_tbl" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_duplicate" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +NOTICE: created index "mv_ivm_distinct_index" on materialized view "mv_ivm_distinct" +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 20 + 30 + 40 + 50 +(6 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +ROLLBACK; +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 120 | 2 | 60.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+---------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 220 | 2 | 110.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 20 | 1 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 120 | 2 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; + sum | count +-----+------- +(0 rows) + +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; + i | sum | count +---+-----+------- +(0 rows) + +ROLLBACK; +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 150 | 5 | 30.0000000000000000 +(1 row) + +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 210 | 6 | 35.0000000000000000 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +NOTICE: created index "mv_ivm_avg_bug_index" on materialized view "mv_ivm_avg_bug" +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 3 | 3.3333333333333333 + 2 | 80 | 3 | 26.6666666666666667 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_min_max_index" on materialized view "mv_ivm_min_max" +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 10 + 2 | 20 | 20 + 3 | 30 | 30 + 4 | 40 | 40 + 5 | 50 | 50 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 12 + 2 | 20 | 22 + 3 | 30 | 32 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 11 | 12 + 2 | 20 | 22 + 3 | 30 | 31 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min_max" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 50 +(1 row) + +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 0 | 70 +(1 row) + +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 60 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + | +(1 row) + +ROLLBACK; +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min; + min +----- + 10 +(1 row) + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + min +----- + 20 +(1 row) + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; + min +----- + 30 +(1 row) + +ROLLBACK; +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | sum +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | b +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ERROR: too many column names were specified +ROLLBACK; +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +NOTICE: could not create an index on materialized view "mv_self" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +----+---- + 10 | 10 + 20 | 20 + 30 | 30 +(3 rows) + +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 30 | 30 + 40 | 40 + 200 | 200 +(3 rows) + +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 130 | 130 + 300 | 300 +(4 rows) + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 70 | 70 + 70 | 77 + 77 | 70 + 77 | 77 + 130 | 130 + 300 | 300 +(8 rows) + +ROLLBACK; +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY v1; + v1 | v2 +----+----- + 10 | 100 + 20 | 200 + 30 | 300 +(3 rows) + +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv ORDER BY v1; + v1 | v2 +------+----- + 10 | 100 + 11 | 100 + 1020 | 200 + 1020 | 222 +(4 rows) + +ROLLBACK; +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +NOTICE: created index "mv_ri_index" on materialized view "mv_ri" +SELECT * FROM mv_ri ORDER BY i1; + i1 | i2 +----+---- + 1 | 1 + 2 | 2 + 3 | 3 +(3 rows) + +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; + i1 | i2 +----+---- + 3 | 3 + 10 | 10 +(2 rows) + +ROLLBACK; +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | +(2 rows) + +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | 20 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i +--- +(0 rows) + +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; + i +--- + 1 + +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 30 + | 3 +(2 rows) + +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 300 + | 30 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 1 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 4 +(1 row) + +ROLLBACK; +-- IMMV containing user defined type +BEGIN; +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: return type mytype is only a shell +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: argument type mytype is only a shell +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +NOTICE: could not create an index on materialized view "mv_mytype" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + x +--- + 1 +(1 row) + +ROLLBACK; +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +ERROR: OUTER JOIN is not supported on incrementally maintainable materialized view +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +ERROR: CTE is not supported on incrementally maintainable materialized view +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +ERROR: ORDER BY clause is not supported on incrementally maintainable materialized view +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; +ERROR: HAVING clause is not supported on incrementally maintainable materialized view +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; +ERROR: mutable function is not supported on incrementally maintainable materialized view +HINT: functions must be marked IMMUTABLE +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; +ERROR: LIMIT/OFFSET clause is not supported on incrementally maintainable materialized view +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; +ERROR: DISTINCT ON is not supported on incrementally maintainable materialized view +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); +ERROR: TABLESAMPLE clause is not supported on incrementally maintainable materialized view +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; +ERROR: window functions are not supported on incrementally maintainable materialized view +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +ERROR: aggregate function with FILTER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +ERROR: aggregate function with DISTINCT arguments is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +ERROR: aggregate function with ORDER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); +ERROR: GROUPING SETS, ROLLUP, or CUBE clauses is not supported on incrementally maintainable materialized view +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ERROR: inheritance parent is not supported on incrementally maintainable materialized view +ROLLBACK; +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; +ERROR: UNION/INTERSECT/EXCEPT statements are not supported on incrementally maintainable materialized view +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; +ERROR: empty target list is not supported on incrementally maintainable materialized view +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; +ERROR: FOR UPDATE/SHARE clause is not supported on incrementally maintainable materialized view +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; +ERROR: column name __ivm_count__ is not supported on incrementally maintainable materialized view +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; +ERROR: GROUP BY expression not appearing in select list is not supported on incrementally maintainable materialized view +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); +ERROR: VALUES is not supported on incrementally maintainable materialized view +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +NOTICE: role "regress_ivm_admin" does not exist, skipping +DROP USER IF EXISTS regress_ivm_user; +NOTICE: role "regress_ivm_user" does not exist, skipping +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +NOTICE: could not create an index on materialized view "ivm_rls" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user +(1 row) + +RESET SESSION AUTHORIZATION; +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user + 3 | baz | regress_ivm_user +(2 rows) + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +-- +(1 row) + +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+-------+------------------ + 2 | bar | regress_ivm_user + 3 | baz | regress_ivm_user + 6 | corge | regress_ivm_user +(3 rows) + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +NOTICE: could not create an index on materialized view "ivm_rls2" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +RESET SESSION AUTHORIZATION; +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +-- +(1 row) + +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + id | data | owner | num +----+-------+------------------+--------- + 2 | bar | regress_ivm_user | two + 3 | baz_2 | regress_ivm_user | three_2 + 6 | corge | regress_ivm_user | six +(3 rows) + +-- automatic index creation +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; +NOTICE: created index "mv_idx1_index" on materialized view "mv_idx1" +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; +NOTICE: created index "mv_idx2_index" on materialized view "mv_idx2" +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; +NOTICE: created index "mv_idx3_index" on materialized view "mv_idx3" +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +NOTICE: could not create an index on materialized view "mv_idx4" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; +NOTICE: could not create an index on materialized view "mv_idx5" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +-- cleanup +DROP TABLE rls_tbl CASCADE; +NOTICE: drop cascades to 2 other objects +DETAIL: drop cascades to materialized view ivm_rls +drop cascades to materialized view ivm_rls2 +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; +DROP TABLE mv_base_b CASCADE; +NOTICE: drop cascades to 3 other objects +DETAIL: drop cascades to materialized view mv_ivm_1 +drop cascades to view b_view +drop cascades to materialized view b_mview +DROP TABLE mv_base_a CASCADE; diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index 2429ec2bba..03814f34e9 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -78,7 +78,7 @@ test: brin_bloom brin_multi # psql depends on create_am # amutils depends on geometry, create_index_spgist, hash_index, brin # ---------- -test: create_table_like alter_generic alter_operator misc async dbsize merge misc_functions sysviews tsrf tid tidscan tidrangescan collate.utf8 collate.icu.utf8 incremental_sort create_role +test: create_table_like alter_generic alter_operator misc async dbsize merge misc_functions sysviews tsrf tid tidscan tidrangescan collate.utf8 collate.icu.utf8 incremental_sort create_role incremental_matview # collate.linux.utf8 and collate.icu.utf8 tests cannot be run in parallel with each other test: rules psql psql_crosstab amutils stats_ext collate.linux.utf8 collate.windows.win1252 diff --git a/src/test/regress/sql/incremental_matview.sql b/src/test/regress/sql/incremental_matview.sql new file mode 100644 index 0000000000..90116edff8 --- /dev/null +++ b/src/test/regress/sql/incremental_matview.sql @@ -0,0 +1,533 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (i int, j int); +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +CREATE TABLE mv_base_b (i int, k int); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); + +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +REFRESH MATERIALIZED VIEW mv_ivm_1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; + +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; +ROLLBACK; + +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +DROP MATERIALIZED VIEW mv_ivm_rename; + +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +DROP MATERIALIZED VIEW mv_ivm_unique; + +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +ROLLBACK; + +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +ROLLBACK; + +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +ROLLBACK; + +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +ROLLBACK; + +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +ROLLBACK; + +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min; + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); + +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; +ROLLBACK; + +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +SELECT * FROM mv_self ORDER BY v1; +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; +SELECT * FROM mv_self ORDER BY v1; + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + +ROLLBACK; + +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +SELECT * FROM mv ORDER BY v1; +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; +SELECT * FROM mv ORDER BY v1; +ROLLBACK; + +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +SELECT * FROM mv_ri ORDER BY i1; +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; +ROLLBACK; + +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +-- IMMV containing user defined type +BEGIN; + +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); + +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; + +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); + +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); + +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + +ROLLBACK; + +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; + +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; + +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; + +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; + +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; + +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); + +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; + +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); + +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ROLLBACK; + +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; + +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; + +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; + +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; + +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; + +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; + +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); + +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +DROP USER IF EXISTS regress_ivm_user; +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; + +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); + +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; + +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; + +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; +RESET SESSION AUTHORIZATION; + +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +RESET SESSION AUTHORIZATION; + +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + +-- automatic index creation +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); + +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; + +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; + +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; + +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; + +-- cleanup + +DROP TABLE rls_tbl CASCADE; +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; + +DROP TABLE mv_base_b CASCADE; +DROP TABLE mv_base_a CASCADE; -- 2.25.1 --Multipart=_Tue__2_Jul_2024_17_03_11_+0900_6OrVBZxOB4o_k6A1 Content-Type: text/x-diff; name="v33-0009-Add-support-for-min-max-aggregates-for-IVM.patch" Content-Disposition: attachment; filename="v33-0009-Add-support-for-min-max-aggregates-for-IVM.patch" Content-Transfer-Encoding: 7bit ^ permalink raw reply [nested|flat] 78+ messages in thread
* [PATCH v24 09/15] Add regression tests for Incremental View Maintenance @ 2021-03-10 02:11 Takuma Hoshiai <[email protected]> 0 siblings, 0 replies; 78+ messages in thread From: Takuma Hoshiai @ 2021-03-10 02:11 UTC (permalink / raw) --- .../regress/expected/incremental_matview.out | 812 ++++++++++++++++++ src/test/regress/parallel_schedule | 2 +- src/test/regress/sql/incremental_matview.sql | 400 +++++++++ 3 files changed, 1213 insertions(+), 1 deletion(-) create mode 100644 src/test/regress/expected/incremental_matview.out create mode 100644 src/test/regress/sql/incremental_matview.sql diff --git a/src/test/regress/expected/incremental_matview.out b/src/test/regress/expected/incremental_matview.out new file mode 100644 index 0000000000..4b14100acd --- /dev/null +++ b/src/test/regress/expected/incremental_matview.out @@ -0,0 +1,812 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (i int, j int); +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +CREATE TABLE mv_base_b (i int, k int); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +NOTICE: could not create an index on materialized view "mv_ivm_1" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ERROR: materialized view "mv_ivm_1" has not been populated +HINT: Use the REFRESH MATERIALIZED VIEW command. +REFRESH MATERIALIZED VIEW mv_ivm_1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_rename_index" on materialized view "mv_ivm_rename" +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +ERROR: IVM column can not be renamed +DROP MATERIALIZED VIEW mv_ivm_rename; +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_unique_index" on materialized view "mv_ivm_unique" +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +ERROR: unique index creation on IVM columns is not supported +DROP MATERIALIZED VIEW mv_ivm_unique; +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +NOTICE: could not create an index on materialized view "mv_ivm_func" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +NOTICE: could not create an index on materialized view "mv_ivm_no_tbl" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_duplicate" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +NOTICE: created index "mv_ivm_distinct_index" on materialized view "mv_ivm_distinct" +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 20 + 30 + 40 + 50 +(6 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +ROLLBACK; +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 120 | 2 | 60.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+---------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 220 | 2 | 110.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 20 | 1 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 120 | 2 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +ROLLBACK; +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 150 | 5 | 30.0000000000000000 +(1 row) + +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 210 | 6 | 35.0000000000000000 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +NOTICE: created index "mv_ivm_avg_bug_index" on materialized view "mv_ivm_avg_bug" +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 3 | 3.3333333333333333 + 2 | 80 | 3 | 26.6666666666666667 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_min_max_index" on materialized view "mv_ivm_min_max" +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 10 + 2 | 20 | 20 + 3 | 30 | 30 + 4 | 40 | 40 + 5 | 50 | 50 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 12 + 2 | 20 | 22 + 3 | 30 | 32 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 11 | 12 + 2 | 20 | 22 + 3 | 30 | 31 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min_max" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 50 +(1 row) + +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 0 | 70 +(1 row) + +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 60 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + | +(1 row) + +ROLLBACK; +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +NOTICE: could not create an index on materialized view "mv_self" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +----+---- + 10 | 10 + 20 | 20 + 30 | 30 +(3 rows) + +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 30 | 30 + 40 | 40 + 200 | 200 +(3 rows) + +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 130 | 130 + 300 | 300 +(4 rows) + +ROLLBACK; +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY v1; + v1 | v2 +----+----- + 10 | 100 + 20 | 200 + 30 | 300 +(3 rows) + +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv ORDER BY v1; + v1 | v2 +------+----- + 10 | 100 + 11 | 100 + 1020 | 200 + 1020 | 222 +(4 rows) + +ROLLBACK; +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +NOTICE: created index "mv_ri_index" on materialized view "mv_ri" +SELECT * FROM mv_ri ORDER BY i1; + i1 | i2 +----+---- + 1 | 1 + 2 | 2 + 3 | 3 +(3 rows) + +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; + i1 | i2 +----+---- + 3 | 3 + 10 | 10 +(2 rows) + +ROLLBACK; +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | +(2 rows) + +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | 20 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i +--- +(0 rows) + +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; + i +--- + 1 + +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 30 + | 3 +(2 rows) + +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 300 + | 30 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 1 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 4 +(1 row) + +ROLLBACK; +-- IMMV containing user defined type +BEGIN; +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: return type mytype is only a shell +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: argument type mytype is only a shell +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +NOTICE: could not create an index on materialized view "mv_mytype" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + x +--- + 1 +(1 row) + +ROLLBACK; +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +ERROR: OUTER JOIN is not supported on incrementally maintainable materialized view +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +ERROR: CTE is not supported on incrementally maintainable materialized view +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +ERROR: ORDER BY clause is not supported on incrementally maintainable materialized view +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; +ERROR: HAVING clause is not supported on incrementally maintainable materialized view +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; +ERROR: mutable function is not supported on incrementally maintainable materialized view +HINT: functions must be marked IMMUTABLE +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; +ERROR: LIMIT/OFFSET clause is not supported on incrementally maintainable materialized view +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; +ERROR: DISTINCT ON is not supported on incrementally maintainable materialized view +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); +ERROR: TABLESAMPLE clause is not supported on incrementally maintainable materialized view +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; +ERROR: window functions are not supported on incrementally maintainable materialized view +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +ERROR: aggregate function with FILTER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +ERROR: aggregate function with DISTINCT arguments is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +ERROR: aggregate function with ORDER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); +ERROR: GROUPING SETS, ROLLUP, or CUBE clauses is not supported on incrementally maintainable materialized view +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ERROR: inheritance parent is not supported on incrementally maintainable materialized view +ROLLBACK; +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; +ERROR: UNION/INTERSECT/EXCEPT statements are not supported on incrementally maintainable materialized view +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; +ERROR: empty target list is not supported on incrementally maintainable materialized view +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; +ERROR: FOR UPDATE/SHARE clause is not supported on incrementally maintainable materialized view +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; +ERROR: column name __ivm_count__ is not supported on incrementally maintainable materialized view +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; +ERROR: GROUP BY expression not appearing in select list is not supported on incrementally maintainable materialized view +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); +ERROR: VALUES is not supported on incrementally maintainable materialized view +-- base table which has row level security +DROP USER IF EXISTS ivm_admin; +NOTICE: role "ivm_admin" does not exist, skipping +DROP USER IF EXISTS ivm_user; +NOTICE: role "ivm_user" does not exist, skipping +CREATE USER ivm_admin; +CREATE USER ivm_user; +SET SESSION AUTHORIZATION ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'); +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +CREATE POLICY rls_tbl_policy2 ON rls_tbl FOR INSERT TO PUBLIC WITH CHECK(current_user LIKE 'ivm_%'); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; +SET SESSION AUTHORIZATION ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +NOTICE: could not create an index on materialized view "ivm_rls" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+---------- + 1 | foo | ivm_user +(1 row) + +INSERT INTO rls_tbl VALUES + (3,'baz','ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+---------- + 1 | foo | ivm_user + 3 | baz | ivm_user +(2 rows) + +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +NOTICE: could not create an index on materialized view "ivm_rls2" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +RESET SESSION AUTHORIZATION; +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +-- +(1 row) + +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + id | data | owner | num +----+-------+----------+--------- + 1 | foo | ivm_user | one + 3 | baz_2 | ivm_user | three_2 +(2 rows) + +DROP TABLE rls_tbl CASCADE; +NOTICE: drop cascades to 2 other objects +DETAIL: drop cascades to materialized view ivm_rls +drop cascades to materialized view ivm_rls2 +DROP TABLE num_tbl CASCADE; +DROP USER ivm_user; +DROP USER ivm_admin; +DROP TABLE mv_base_b CASCADE; +NOTICE: drop cascades to 3 other objects +DETAIL: drop cascades to materialized view mv_ivm_1 +drop cascades to view b_view +drop cascades to materialized view b_mview +DROP TABLE mv_base_a CASCADE; diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index 7be89178f0..b0350f47dd 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -86,7 +86,7 @@ test: brin_bloom brin_multi # ---------- # Another group of parallel tests # ---------- -test: create_table_like alter_generic alter_operator misc async dbsize misc_functions sysviews tsrf tid tidscan tidrangescan collate.icu.utf8 incremental_sort +test: create_table_like alter_generic alter_operator misc async dbsize misc_functions sysviews tsrf tid tidscan tidrangescan collate.icu.utf8 incremental_sort incremental_matview # rules cannot run concurrently with any test that creates # a view or rule in the public schema diff --git a/src/test/regress/sql/incremental_matview.sql b/src/test/regress/sql/incremental_matview.sql new file mode 100644 index 0000000000..311e9b96fb --- /dev/null +++ b/src/test/regress/sql/incremental_matview.sql @@ -0,0 +1,400 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (i int, j int); +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +CREATE TABLE mv_base_b (i int, k int); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); + +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +REFRESH MATERIALIZED VIEW mv_ivm_1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +DROP MATERIALIZED VIEW mv_ivm_rename; + +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +DROP MATERIALIZED VIEW mv_ivm_unique; + +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +ROLLBACK; + +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +ROLLBACK; + +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +ROLLBACK; + +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +ROLLBACK; + +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +ROLLBACK; + +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +ROLLBACK; + +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +SELECT * FROM mv_self ORDER BY v1; +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; +SELECT * FROM mv_self ORDER BY v1; +ROLLBACK; + +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +SELECT * FROM mv ORDER BY v1; +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; +SELECT * FROM mv ORDER BY v1; +ROLLBACK; + +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +SELECT * FROM mv_ri ORDER BY i1; +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; +ROLLBACK; + +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +-- IMMV containing user defined type +BEGIN; + +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); + +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; + +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); + +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); + +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + +ROLLBACK; + +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; + +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; + +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; + +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; + +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; + +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); + +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; + +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); + +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ROLLBACK; + +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; + +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; + +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; + +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; + +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; + +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; + +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); + +-- base table which has row level security +DROP USER IF EXISTS ivm_admin; +DROP USER IF EXISTS ivm_user; +CREATE USER ivm_admin; +CREATE USER ivm_user; +SET SESSION AUTHORIZATION ivm_admin; + +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'); +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +CREATE POLICY rls_tbl_policy2 ON rls_tbl FOR INSERT TO PUBLIC WITH CHECK(current_user LIKE 'ivm_%'); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; + +SET SESSION AUTHORIZATION ivm_user; + +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; +INSERT INTO rls_tbl VALUES + (3,'baz','ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); + +RESET SESSION AUTHORIZATION; + +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + +DROP TABLE rls_tbl CASCADE; +DROP TABLE num_tbl CASCADE; +DROP USER ivm_user; +DROP USER ivm_admin; + +DROP TABLE mv_base_b CASCADE; +DROP TABLE mv_base_a CASCADE; -- 2.17.1 --Multipart=_Thu__23_Sep_2021_04_57_30_+0900_b5pmgR1N8oMaMz.U Content-Type: text/x-diff; name="v24-0010-Add-documentations-about-Incremental-View-Mainte.patch" Content-Disposition: attachment; filename="v24-0010-Add-documentations-about-Incremental-View-Mainte.patch" Content-Transfer-Encoding: 7bit ^ permalink raw reply [nested|flat] 78+ messages in thread
* [PATCH v30 10/11] Add regression tests for Incremental View Maintenance @ 2021-03-10 02:11 Takuma Hoshiai <[email protected]> 0 siblings, 0 replies; 78+ messages in thread From: Takuma Hoshiai @ 2021-03-10 02:11 UTC (permalink / raw) --- .../regress/expected/incremental_matview.out | 1030 +++++++++++++++++ src/test/regress/parallel_schedule | 2 +- src/test/regress/sql/incremental_matview.sql | 533 +++++++++ 3 files changed, 1564 insertions(+), 1 deletion(-) create mode 100644 src/test/regress/expected/incremental_matview.out create mode 100644 src/test/regress/sql/incremental_matview.sql diff --git a/src/test/regress/expected/incremental_matview.out b/src/test/regress/expected/incremental_matview.out new file mode 100644 index 0000000000..8946d09f5d --- /dev/null +++ b/src/test/regress/expected/incremental_matview.out @@ -0,0 +1,1030 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (i int, j int); +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +CREATE TABLE mv_base_b (i int, k int); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ERROR: materialized view "mv_ivm_1" has not been populated +HINT: Use the REFRESH MATERIALIZED VIEW command. +REFRESH MATERIALIZED VIEW mv_ivm_1; +NOTICE: could not create an index on materialized view "mv_ivm_1" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 17 +(1 row) + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 1 +(1 row) + +ROLLBACK; +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_rename_index" on materialized view "mv_ivm_rename" +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +ERROR: IVM column can not be renamed +DROP MATERIALIZED VIEW mv_ivm_rename; +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_unique_index" on materialized view "mv_ivm_unique" +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +ERROR: unique index creation on IVM columns is not supported +DROP MATERIALIZED VIEW mv_ivm_unique; +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +NOTICE: could not create an index on materialized view "mv_ivm_func" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +NOTICE: could not create an index on materialized view "mv_ivm_no_tbl" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_duplicate" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +NOTICE: created index "mv_ivm_distinct_index" on materialized view "mv_ivm_distinct" +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 20 + 30 + 40 + 50 +(6 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +ROLLBACK; +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 120 | 2 | 60.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+---------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 220 | 2 | 110.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 20 | 1 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 120 | 2 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; + sum | count +-----+------- +(0 rows) + +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; + i | sum | count +---+-----+------- +(0 rows) + +ROLLBACK; +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 150 | 5 | 30.0000000000000000 +(1 row) + +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 210 | 6 | 35.0000000000000000 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +NOTICE: created index "mv_ivm_avg_bug_index" on materialized view "mv_ivm_avg_bug" +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 3 | 3.3333333333333333 + 2 | 80 | 3 | 26.6666666666666667 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_min_max_index" on materialized view "mv_ivm_min_max" +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 10 + 2 | 20 | 20 + 3 | 30 | 30 + 4 | 40 | 40 + 5 | 50 | 50 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 12 + 2 | 20 | 22 + 3 | 30 | 32 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 11 | 12 + 2 | 20 | 22 + 3 | 30 | 31 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min_max" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 50 +(1 row) + +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 0 | 70 +(1 row) + +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 60 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + | +(1 row) + +ROLLBACK; +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min; + min +----- + 10 +(1 row) + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + min +----- + 20 +(1 row) + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; + min +----- + 30 +(1 row) + +ROLLBACK; +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | sum +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | b +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ERROR: too many column names were specified +ROLLBACK; +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +NOTICE: could not create an index on materialized view "mv_self" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +----+---- + 10 | 10 + 20 | 20 + 30 | 30 +(3 rows) + +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 30 | 30 + 40 | 40 + 200 | 200 +(3 rows) + +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 130 | 130 + 300 | 300 +(4 rows) + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 70 | 70 + 70 | 77 + 77 | 70 + 77 | 77 + 130 | 130 + 300 | 300 +(8 rows) + +ROLLBACK; +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY v1; + v1 | v2 +----+----- + 10 | 100 + 20 | 200 + 30 | 300 +(3 rows) + +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv ORDER BY v1; + v1 | v2 +------+----- + 10 | 100 + 11 | 100 + 1020 | 200 + 1020 | 222 +(4 rows) + +ROLLBACK; +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +NOTICE: created index "mv_ri_index" on materialized view "mv_ri" +SELECT * FROM mv_ri ORDER BY i1; + i1 | i2 +----+---- + 1 | 1 + 2 | 2 + 3 | 3 +(3 rows) + +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; + i1 | i2 +----+---- + 3 | 3 + 10 | 10 +(2 rows) + +ROLLBACK; +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | +(2 rows) + +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | 20 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i +--- +(0 rows) + +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; + i +--- + 1 + +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 30 + | 3 +(2 rows) + +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 300 + | 30 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 1 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 4 +(1 row) + +ROLLBACK; +-- IMMV containing user defined type +BEGIN; +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: return type mytype is only a shell +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: argument type mytype is only a shell +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +NOTICE: could not create an index on materialized view "mv_mytype" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + x +--- + 1 +(1 row) + +ROLLBACK; +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +ERROR: OUTER JOIN is not supported on incrementally maintainable materialized view +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +ERROR: CTE is not supported on incrementally maintainable materialized view +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +ERROR: ORDER BY clause is not supported on incrementally maintainable materialized view +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; +ERROR: HAVING clause is not supported on incrementally maintainable materialized view +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; +ERROR: mutable function is not supported on incrementally maintainable materialized view +HINT: functions must be marked IMMUTABLE +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; +ERROR: LIMIT/OFFSET clause is not supported on incrementally maintainable materialized view +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; +ERROR: DISTINCT ON is not supported on incrementally maintainable materialized view +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); +ERROR: TABLESAMPLE clause is not supported on incrementally maintainable materialized view +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; +ERROR: window functions are not supported on incrementally maintainable materialized view +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +ERROR: aggregate function with FILTER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +ERROR: aggregate function with DISTINCT arguments is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +ERROR: aggregate function with ORDER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); +ERROR: GROUPING SETS, ROLLUP, or CUBE clauses is not supported on incrementally maintainable materialized view +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ERROR: inheritance parent is not supported on incrementally maintainable materialized view +ROLLBACK; +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; +ERROR: UNION/INTERSECT/EXCEPT statements are not supported on incrementally maintainable materialized view +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; +ERROR: empty target list is not supported on incrementally maintainable materialized view +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; +ERROR: FOR UPDATE/SHARE clause is not supported on incrementally maintainable materialized view +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; +ERROR: column name __ivm_count__ is not supported on incrementally maintainable materialized view +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; +ERROR: GROUP BY expression not appearing in select list is not supported on incrementally maintainable materialized view +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); +ERROR: VALUES is not supported on incrementally maintainable materialized view +-- views containing base tables with Row Level Security +DROP USER IF EXISTS ivm_admin; +NOTICE: role "ivm_admin" does not exist, skipping +DROP USER IF EXISTS ivm_user; +NOTICE: role "ivm_user" does not exist, skipping +CREATE USER ivm_admin; +CREATE USER ivm_user; +--- create a table with RLS +SET SESSION AUTHORIZATION ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; +--- create a view owned by ivm_user +SET SESSION AUTHORIZATION ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +NOTICE: could not create an index on materialized view "ivm_rls" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+---------- + 1 | foo | ivm_user +(1 row) + +RESET SESSION AUTHORIZATION; +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+---------- + 1 | foo | ivm_user + 3 | baz | ivm_user +(2 rows) + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'ivm_user' WHERE id = 2) +SELECT; +-- +(1 row) + +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+-------+---------- + 2 | bar | ivm_user + 3 | baz | ivm_user + 6 | corge | ivm_user +(3 rows) + +--- +SET SESSION AUTHORIZATION ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +NOTICE: could not create an index on materialized view "ivm_rls2" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +RESET SESSION AUTHORIZATION; +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +-- +(1 row) + +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + id | data | owner | num +----+-------+----------+--------- + 2 | bar | ivm_user | two + 3 | baz_2 | ivm_user | three_2 + 6 | corge | ivm_user | six +(3 rows) + +-- automatic index creation +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; +NOTICE: created index "mv_idx1_index" on materialized view "mv_idx1" +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; +NOTICE: created index "mv_idx2_index" on materialized view "mv_idx2" +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; +NOTICE: created index "mv_idx3_index" on materialized view "mv_idx3" +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +NOTICE: could not create an index on materialized view "mv_idx4" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; +NOTICE: could not create an index on materialized view "mv_idx5" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +-- cleanup +DROP TABLE rls_tbl CASCADE; +NOTICE: drop cascades to 2 other objects +DETAIL: drop cascades to materialized view ivm_rls +drop cascades to materialized view ivm_rls2 +DROP TABLE num_tbl CASCADE; +DROP USER ivm_user; +DROP USER ivm_admin; +DROP TABLE mv_base_b CASCADE; +NOTICE: drop cascades to 3 other objects +DETAIL: drop cascades to materialized view mv_ivm_1 +drop cascades to view b_view +drop cascades to materialized view b_mview +DROP TABLE mv_base_a CASCADE; diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index 1d8a414eea..84c3c5e9be 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -78,7 +78,7 @@ test: brin_bloom brin_multi # psql depends on create_am # amutils depends on geometry, create_index_spgist, hash_index, brin # ---------- -test: create_table_like alter_generic alter_operator misc async dbsize merge misc_functions sysviews tsrf tid tidscan tidrangescan collate.icu.utf8 incremental_sort create_role without_overlaps +test: create_table_like alter_generic alter_operator misc async dbsize merge misc_functions sysviews tsrf tid tidscan tidrangescan collate.icu.utf8 incremental_sort create_role without_overlaps incremental_matview # collate.*.utf8 tests cannot be run in parallel with each other test: rules psql psql_crosstab amutils stats_ext collate.linux.utf8 collate.windows.win1252 diff --git a/src/test/regress/sql/incremental_matview.sql b/src/test/regress/sql/incremental_matview.sql new file mode 100644 index 0000000000..82686f9324 --- /dev/null +++ b/src/test/regress/sql/incremental_matview.sql @@ -0,0 +1,533 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (i int, j int); +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +CREATE TABLE mv_base_b (i int, k int); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); + +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +REFRESH MATERIALIZED VIEW mv_ivm_1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; + +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; +ROLLBACK; + +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +DROP MATERIALIZED VIEW mv_ivm_rename; + +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +DROP MATERIALIZED VIEW mv_ivm_unique; + +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +ROLLBACK; + +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +ROLLBACK; + +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +ROLLBACK; + +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +ROLLBACK; + +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +ROLLBACK; + +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min; + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); + +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; +ROLLBACK; + +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +SELECT * FROM mv_self ORDER BY v1; +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; +SELECT * FROM mv_self ORDER BY v1; + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + +ROLLBACK; + +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +SELECT * FROM mv ORDER BY v1; +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; +SELECT * FROM mv ORDER BY v1; +ROLLBACK; + +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +SELECT * FROM mv_ri ORDER BY i1; +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; +ROLLBACK; + +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +-- IMMV containing user defined type +BEGIN; + +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); + +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; + +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); + +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); + +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + +ROLLBACK; + +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; + +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; + +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; + +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; + +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; + +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); + +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; + +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); + +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ROLLBACK; + +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; + +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; + +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; + +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; + +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; + +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; + +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); + +-- views containing base tables with Row Level Security +DROP USER IF EXISTS ivm_admin; +DROP USER IF EXISTS ivm_user; +CREATE USER ivm_admin; +CREATE USER ivm_user; + +--- create a table with RLS +SET SESSION AUTHORIZATION ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); + +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; + +--- create a view owned by ivm_user +SET SESSION AUTHORIZATION ivm_user; + +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; +RESET SESSION AUTHORIZATION; + +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'ivm_user' WHERE id = 2) +SELECT; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- +SET SESSION AUTHORIZATION ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +RESET SESSION AUTHORIZATION; + +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + +-- automatic index creation +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); + +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; + +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; + +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; + +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; + +-- cleanup + +DROP TABLE rls_tbl CASCADE; +DROP TABLE num_tbl CASCADE; +DROP USER ivm_user; +DROP USER ivm_admin; + +DROP TABLE mv_base_b CASCADE; +DROP TABLE mv_base_a CASCADE; -- 2.25.1 --Multipart=_Mon__4_Mar_2024_11_58_46_+0900_UaponF/qQhQrVCFt Content-Type: text/x-diff; name="v30-0011-Add-documentations-about-Incremental-View-Mainte.patch" Content-Disposition: attachment; filename="v30-0011-Add-documentations-about-Incremental-View-Mainte.patch" Content-Transfer-Encoding: 7bit ^ permalink raw reply [nested|flat] 78+ messages in thread
* [PATCH v27 8/9] Add regression tests for Incremental View Maintenance @ 2021-03-10 02:11 Takuma Hoshiai <[email protected]> 0 siblings, 0 replies; 78+ messages in thread From: Takuma Hoshiai @ 2021-03-10 02:11 UTC (permalink / raw) --- .../regress/expected/incremental_matview.out | 840 ++++++++++++++++++ src/test/regress/parallel_schedule | 2 +- src/test/regress/sql/incremental_matview.sql | 424 +++++++++ 3 files changed, 1265 insertions(+), 1 deletion(-) create mode 100644 src/test/regress/expected/incremental_matview.out create mode 100644 src/test/regress/sql/incremental_matview.sql diff --git a/src/test/regress/expected/incremental_matview.out b/src/test/regress/expected/incremental_matview.out new file mode 100644 index 0000000000..201af5f087 --- /dev/null +++ b/src/test/regress/expected/incremental_matview.out @@ -0,0 +1,840 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (i int, j int); +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +CREATE TABLE mv_base_b (i int, k int); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ERROR: materialized view "mv_ivm_1" has not been populated +HINT: Use the REFRESH MATERIALIZED VIEW command. +REFRESH MATERIALIZED VIEW mv_ivm_1; +NOTICE: could not create an index on materialized view "mv_ivm_1" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 13 +(1 row) + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 1 +(1 row) + +ROLLBACK; +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_rename_index" on materialized view "mv_ivm_rename" +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +ERROR: IVM column can not be renamed +DROP MATERIALIZED VIEW mv_ivm_rename; +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_unique_index" on materialized view "mv_ivm_unique" +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +ERROR: unique index creation on IVM columns is not supported +DROP MATERIALIZED VIEW mv_ivm_unique; +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +NOTICE: could not create an index on materialized view "mv_ivm_func" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +NOTICE: could not create an index on materialized view "mv_ivm_no_tbl" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_duplicate" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +NOTICE: created index "mv_ivm_distinct_index" on materialized view "mv_ivm_distinct" +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 20 + 30 + 40 + 50 +(6 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +ROLLBACK; +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 120 | 2 | 60.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+---------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 220 | 2 | 110.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 20 | 1 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 120 | 2 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +ROLLBACK; +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 150 | 5 | 30.0000000000000000 +(1 row) + +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 210 | 6 | 35.0000000000000000 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +NOTICE: created index "mv_ivm_avg_bug_index" on materialized view "mv_ivm_avg_bug" +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 3 | 3.3333333333333333 + 2 | 80 | 3 | 26.6666666666666667 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_min_max_index" on materialized view "mv_ivm_min_max" +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 10 + 2 | 20 | 20 + 3 | 30 | 30 + 4 | 40 | 40 + 5 | 50 | 50 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 12 + 2 | 20 | 22 + 3 | 30 | 32 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 11 | 12 + 2 | 20 | 22 + 3 | 30 | 31 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min_max" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 50 +(1 row) + +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 0 | 70 +(1 row) + +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 60 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + | +(1 row) + +ROLLBACK; +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +NOTICE: could not create an index on materialized view "mv_self" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +----+---- + 10 | 10 + 20 | 20 + 30 | 30 +(3 rows) + +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 30 | 30 + 40 | 40 + 200 | 200 +(3 rows) + +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 130 | 130 + 300 | 300 +(4 rows) + +ROLLBACK; +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY v1; + v1 | v2 +----+----- + 10 | 100 + 20 | 200 + 30 | 300 +(3 rows) + +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv ORDER BY v1; + v1 | v2 +------+----- + 10 | 100 + 11 | 100 + 1020 | 200 + 1020 | 222 +(4 rows) + +ROLLBACK; +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +NOTICE: created index "mv_ri_index" on materialized view "mv_ri" +SELECT * FROM mv_ri ORDER BY i1; + i1 | i2 +----+---- + 1 | 1 + 2 | 2 + 3 | 3 +(3 rows) + +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; + i1 | i2 +----+---- + 3 | 3 + 10 | 10 +(2 rows) + +ROLLBACK; +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | +(2 rows) + +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | 20 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i +--- +(0 rows) + +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; + i +--- + 1 + +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 30 + | 3 +(2 rows) + +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 300 + | 30 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 1 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 4 +(1 row) + +ROLLBACK; +-- IMMV containing user defined type +BEGIN; +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: return type mytype is only a shell +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: argument type mytype is only a shell +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +NOTICE: could not create an index on materialized view "mv_mytype" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + x +--- + 1 +(1 row) + +ROLLBACK; +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +ERROR: OUTER JOIN is not supported on incrementally maintainable materialized view +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +ERROR: CTE is not supported on incrementally maintainable materialized view +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +ERROR: ORDER BY clause is not supported on incrementally maintainable materialized view +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; +ERROR: HAVING clause is not supported on incrementally maintainable materialized view +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; +ERROR: mutable function is not supported on incrementally maintainable materialized view +HINT: functions must be marked IMMUTABLE +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; +ERROR: LIMIT/OFFSET clause is not supported on incrementally maintainable materialized view +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; +ERROR: DISTINCT ON is not supported on incrementally maintainable materialized view +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); +ERROR: TABLESAMPLE clause is not supported on incrementally maintainable materialized view +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; +ERROR: window functions are not supported on incrementally maintainable materialized view +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +ERROR: aggregate function with FILTER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +ERROR: aggregate function with DISTINCT arguments is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +ERROR: aggregate function with ORDER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); +ERROR: GROUPING SETS, ROLLUP, or CUBE clauses is not supported on incrementally maintainable materialized view +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ERROR: inheritance parent is not supported on incrementally maintainable materialized view +ROLLBACK; +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; +ERROR: UNION/INTERSECT/EXCEPT statements are not supported on incrementally maintainable materialized view +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; +ERROR: empty target list is not supported on incrementally maintainable materialized view +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; +ERROR: FOR UPDATE/SHARE clause is not supported on incrementally maintainable materialized view +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; +ERROR: column name __ivm_count__ is not supported on incrementally maintainable materialized view +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; +ERROR: GROUP BY expression not appearing in select list is not supported on incrementally maintainable materialized view +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); +ERROR: VALUES is not supported on incrementally maintainable materialized view +-- base table which has row level security +DROP USER IF EXISTS ivm_admin; +NOTICE: role "ivm_admin" does not exist, skipping +DROP USER IF EXISTS ivm_user; +NOTICE: role "ivm_user" does not exist, skipping +CREATE USER ivm_admin; +CREATE USER ivm_user; +SET SESSION AUTHORIZATION ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'); +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +CREATE POLICY rls_tbl_policy2 ON rls_tbl FOR INSERT TO PUBLIC WITH CHECK(current_user LIKE 'ivm_%'); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; +SET SESSION AUTHORIZATION ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +NOTICE: could not create an index on materialized view "ivm_rls" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+---------- + 1 | foo | ivm_user +(1 row) + +INSERT INTO rls_tbl VALUES + (3,'baz','ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+---------- + 1 | foo | ivm_user + 3 | baz | ivm_user +(2 rows) + +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +NOTICE: could not create an index on materialized view "ivm_rls2" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +RESET SESSION AUTHORIZATION; +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +-- +(1 row) + +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + id | data | owner | num +----+-------+----------+--------- + 1 | foo | ivm_user | one + 3 | baz_2 | ivm_user | three_2 +(2 rows) + +DROP TABLE rls_tbl CASCADE; +NOTICE: drop cascades to 2 other objects +DETAIL: drop cascades to materialized view ivm_rls +drop cascades to materialized view ivm_rls2 +DROP TABLE num_tbl CASCADE; +DROP USER ivm_user; +DROP USER ivm_admin; +DROP TABLE mv_base_b CASCADE; +NOTICE: drop cascades to 3 other objects +DETAIL: drop cascades to materialized view mv_ivm_1 +drop cascades to view b_view +drop cascades to materialized view b_mview +DROP TABLE mv_base_a CASCADE; diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index 103e11483d..3027f4e78c 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -86,7 +86,7 @@ test: brin_bloom brin_multi # psql depends on create_am # amutils depends on geometry, create_index_spgist, hash_index, brin # ---------- -test: create_table_like alter_generic alter_operator misc async dbsize merge misc_functions sysviews tsrf tid tidscan tidrangescan collate.icu.utf8 incremental_sort create_role +test: create_table_like alter_generic alter_operator misc async dbsize merge misc_functions sysviews tsrf tid tidscan tidrangescan collate.icu.utf8 incremental_sort create_role incremental_matview # collate.*.utf8 tests cannot be run in parallel with each other test: rules psql psql_crosstab amutils stats_ext collate.linux.utf8 diff --git a/src/test/regress/sql/incremental_matview.sql b/src/test/regress/sql/incremental_matview.sql new file mode 100644 index 0000000000..a4ce2c741e --- /dev/null +++ b/src/test/regress/sql/incremental_matview.sql @@ -0,0 +1,424 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (i int, j int); +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +CREATE TABLE mv_base_b (i int, k int); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); + +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +REFRESH MATERIALIZED VIEW mv_ivm_1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; + +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; +ROLLBACK; + +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +DROP MATERIALIZED VIEW mv_ivm_rename; + +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +DROP MATERIALIZED VIEW mv_ivm_unique; + +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +ROLLBACK; + +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +ROLLBACK; + +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +ROLLBACK; + +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +ROLLBACK; + +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +ROLLBACK; + +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +ROLLBACK; + +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +SELECT * FROM mv_self ORDER BY v1; +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; +SELECT * FROM mv_self ORDER BY v1; +ROLLBACK; + +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +SELECT * FROM mv ORDER BY v1; +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; +SELECT * FROM mv ORDER BY v1; +ROLLBACK; + +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +SELECT * FROM mv_ri ORDER BY i1; +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; +ROLLBACK; + +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +-- IMMV containing user defined type +BEGIN; + +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); + +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; + +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); + +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); + +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + +ROLLBACK; + +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; + +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; + +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; + +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; + +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; + +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); + +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; + +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); + +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ROLLBACK; + +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; + +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; + +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; + +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; + +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; + +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; + +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); + +-- base table which has row level security +DROP USER IF EXISTS ivm_admin; +DROP USER IF EXISTS ivm_user; +CREATE USER ivm_admin; +CREATE USER ivm_user; +SET SESSION AUTHORIZATION ivm_admin; + +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'); +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +CREATE POLICY rls_tbl_policy2 ON rls_tbl FOR INSERT TO PUBLIC WITH CHECK(current_user LIKE 'ivm_%'); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; + +SET SESSION AUTHORIZATION ivm_user; + +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; +INSERT INTO rls_tbl VALUES + (3,'baz','ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); + +RESET SESSION AUTHORIZATION; + +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + +DROP TABLE rls_tbl CASCADE; +DROP TABLE num_tbl CASCADE; +DROP USER ivm_user; +DROP USER ivm_admin; + +DROP TABLE mv_base_b CASCADE; +DROP TABLE mv_base_a CASCADE; -- 2.17.1 --Multipart=_Fri__22_Apr_2022_14_58_01_+0900_MN3L/o2YUVF2g4zw Content-Type: text/x-diff; name="v27-0009-Add-documentations-about-Incremental-View-Mainte.patch" Content-Disposition: attachment; filename="v27-0009-Add-documentations-about-Incremental-View-Mainte.patch" Content-Transfer-Encoding: 7bit ^ permalink raw reply [nested|flat] 78+ messages in thread
* [PATCH v29 10/11] Add regression tests for Incremental View Maintenance @ 2021-03-10 02:11 Takuma Hoshiai <[email protected]> 0 siblings, 0 replies; 78+ messages in thread From: Takuma Hoshiai @ 2021-03-10 02:11 UTC (permalink / raw) --- src/bin/pg_dump/pg_dump.h | 1 + .../regress/expected/incremental_matview.out | 1030 +++++++++++++++++ src/test/regress/parallel_schedule | 2 +- src/test/regress/sql/incremental_matview.sql | 533 +++++++++ 4 files changed, 1565 insertions(+), 1 deletion(-) create mode 100644 src/test/regress/expected/incremental_matview.out create mode 100644 src/test/regress/sql/incremental_matview.sql diff --git a/src/bin/pg_dump/pg_dump.h b/src/bin/pg_dump/pg_dump.h index 3705891d25..71ea246abd 100644 --- a/src/bin/pg_dump/pg_dump.h +++ b/src/bin/pg_dump/pg_dump.h @@ -323,6 +323,7 @@ typedef struct _tableInfo int numParents; /* number of (immediate) parent tables */ struct _tableInfo **parents; /* TableInfos of immediate parents */ + bool isivm; /* is incrementally maintainable materialized view? */ /* diff --git a/src/test/regress/expected/incremental_matview.out b/src/test/regress/expected/incremental_matview.out new file mode 100644 index 0000000000..8946d09f5d --- /dev/null +++ b/src/test/regress/expected/incremental_matview.out @@ -0,0 +1,1030 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (i int, j int); +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +CREATE TABLE mv_base_b (i int, k int); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ERROR: materialized view "mv_ivm_1" has not been populated +HINT: Use the REFRESH MATERIALIZED VIEW command. +REFRESH MATERIALIZED VIEW mv_ivm_1; +NOTICE: could not create an index on materialized view "mv_ivm_1" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 17 +(1 row) + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 1 +(1 row) + +ROLLBACK; +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_rename_index" on materialized view "mv_ivm_rename" +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +ERROR: IVM column can not be renamed +DROP MATERIALIZED VIEW mv_ivm_rename; +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_unique_index" on materialized view "mv_ivm_unique" +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +ERROR: unique index creation on IVM columns is not supported +DROP MATERIALIZED VIEW mv_ivm_unique; +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +NOTICE: could not create an index on materialized view "mv_ivm_func" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +NOTICE: could not create an index on materialized view "mv_ivm_no_tbl" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_duplicate" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +NOTICE: created index "mv_ivm_distinct_index" on materialized view "mv_ivm_distinct" +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 20 + 30 + 40 + 50 +(6 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +ROLLBACK; +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 120 | 2 | 60.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+---------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 220 | 2 | 110.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 20 | 1 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 120 | 2 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; + sum | count +-----+------- +(0 rows) + +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; + i | sum | count +---+-----+------- +(0 rows) + +ROLLBACK; +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 150 | 5 | 30.0000000000000000 +(1 row) + +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 210 | 6 | 35.0000000000000000 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +NOTICE: created index "mv_ivm_avg_bug_index" on materialized view "mv_ivm_avg_bug" +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 3 | 3.3333333333333333 + 2 | 80 | 3 | 26.6666666666666667 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_min_max_index" on materialized view "mv_ivm_min_max" +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 10 + 2 | 20 | 20 + 3 | 30 | 30 + 4 | 40 | 40 + 5 | 50 | 50 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 12 + 2 | 20 | 22 + 3 | 30 | 32 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 11 | 12 + 2 | 20 | 22 + 3 | 30 | 31 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min_max" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 50 +(1 row) + +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 0 | 70 +(1 row) + +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 60 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + | +(1 row) + +ROLLBACK; +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min; + min +----- + 10 +(1 row) + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + min +----- + 20 +(1 row) + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; + min +----- + 30 +(1 row) + +ROLLBACK; +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | sum +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | b +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ERROR: too many column names were specified +ROLLBACK; +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +NOTICE: could not create an index on materialized view "mv_self" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +----+---- + 10 | 10 + 20 | 20 + 30 | 30 +(3 rows) + +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 30 | 30 + 40 | 40 + 200 | 200 +(3 rows) + +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 130 | 130 + 300 | 300 +(4 rows) + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 70 | 70 + 70 | 77 + 77 | 70 + 77 | 77 + 130 | 130 + 300 | 300 +(8 rows) + +ROLLBACK; +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY v1; + v1 | v2 +----+----- + 10 | 100 + 20 | 200 + 30 | 300 +(3 rows) + +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv ORDER BY v1; + v1 | v2 +------+----- + 10 | 100 + 11 | 100 + 1020 | 200 + 1020 | 222 +(4 rows) + +ROLLBACK; +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +NOTICE: created index "mv_ri_index" on materialized view "mv_ri" +SELECT * FROM mv_ri ORDER BY i1; + i1 | i2 +----+---- + 1 | 1 + 2 | 2 + 3 | 3 +(3 rows) + +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; + i1 | i2 +----+---- + 3 | 3 + 10 | 10 +(2 rows) + +ROLLBACK; +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | +(2 rows) + +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | 20 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i +--- +(0 rows) + +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; + i +--- + 1 + +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 30 + | 3 +(2 rows) + +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 300 + | 30 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 1 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 4 +(1 row) + +ROLLBACK; +-- IMMV containing user defined type +BEGIN; +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: return type mytype is only a shell +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: argument type mytype is only a shell +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +NOTICE: could not create an index on materialized view "mv_mytype" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + x +--- + 1 +(1 row) + +ROLLBACK; +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +ERROR: OUTER JOIN is not supported on incrementally maintainable materialized view +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +ERROR: CTE is not supported on incrementally maintainable materialized view +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +ERROR: ORDER BY clause is not supported on incrementally maintainable materialized view +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; +ERROR: HAVING clause is not supported on incrementally maintainable materialized view +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; +ERROR: mutable function is not supported on incrementally maintainable materialized view +HINT: functions must be marked IMMUTABLE +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; +ERROR: LIMIT/OFFSET clause is not supported on incrementally maintainable materialized view +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; +ERROR: DISTINCT ON is not supported on incrementally maintainable materialized view +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); +ERROR: TABLESAMPLE clause is not supported on incrementally maintainable materialized view +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; +ERROR: window functions are not supported on incrementally maintainable materialized view +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +ERROR: aggregate function with FILTER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +ERROR: aggregate function with DISTINCT arguments is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +ERROR: aggregate function with ORDER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); +ERROR: GROUPING SETS, ROLLUP, or CUBE clauses is not supported on incrementally maintainable materialized view +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ERROR: inheritance parent is not supported on incrementally maintainable materialized view +ROLLBACK; +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; +ERROR: UNION/INTERSECT/EXCEPT statements are not supported on incrementally maintainable materialized view +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; +ERROR: empty target list is not supported on incrementally maintainable materialized view +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; +ERROR: FOR UPDATE/SHARE clause is not supported on incrementally maintainable materialized view +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; +ERROR: column name __ivm_count__ is not supported on incrementally maintainable materialized view +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; +ERROR: GROUP BY expression not appearing in select list is not supported on incrementally maintainable materialized view +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); +ERROR: VALUES is not supported on incrementally maintainable materialized view +-- views containing base tables with Row Level Security +DROP USER IF EXISTS ivm_admin; +NOTICE: role "ivm_admin" does not exist, skipping +DROP USER IF EXISTS ivm_user; +NOTICE: role "ivm_user" does not exist, skipping +CREATE USER ivm_admin; +CREATE USER ivm_user; +--- create a table with RLS +SET SESSION AUTHORIZATION ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; +--- create a view owned by ivm_user +SET SESSION AUTHORIZATION ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +NOTICE: could not create an index on materialized view "ivm_rls" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+---------- + 1 | foo | ivm_user +(1 row) + +RESET SESSION AUTHORIZATION; +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+---------- + 1 | foo | ivm_user + 3 | baz | ivm_user +(2 rows) + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'ivm_user' WHERE id = 2) +SELECT; +-- +(1 row) + +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+-------+---------- + 2 | bar | ivm_user + 3 | baz | ivm_user + 6 | corge | ivm_user +(3 rows) + +--- +SET SESSION AUTHORIZATION ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +NOTICE: could not create an index on materialized view "ivm_rls2" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +RESET SESSION AUTHORIZATION; +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +-- +(1 row) + +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + id | data | owner | num +----+-------+----------+--------- + 2 | bar | ivm_user | two + 3 | baz_2 | ivm_user | three_2 + 6 | corge | ivm_user | six +(3 rows) + +-- automatic index creation +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; +NOTICE: created index "mv_idx1_index" on materialized view "mv_idx1" +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; +NOTICE: created index "mv_idx2_index" on materialized view "mv_idx2" +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; +NOTICE: created index "mv_idx3_index" on materialized view "mv_idx3" +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +NOTICE: could not create an index on materialized view "mv_idx4" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; +NOTICE: could not create an index on materialized view "mv_idx5" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +-- cleanup +DROP TABLE rls_tbl CASCADE; +NOTICE: drop cascades to 2 other objects +DETAIL: drop cascades to materialized view ivm_rls +drop cascades to materialized view ivm_rls2 +DROP TABLE num_tbl CASCADE; +DROP USER ivm_user; +DROP USER ivm_admin; +DROP TABLE mv_base_b CASCADE; +NOTICE: drop cascades to 3 other objects +DETAIL: drop cascades to materialized view mv_ivm_1 +drop cascades to view b_view +drop cascades to materialized view b_mview +DROP TABLE mv_base_a CASCADE; diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index 4df9d8503b..21f7247a07 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -78,7 +78,7 @@ test: brin_bloom brin_multi # psql depends on create_am # amutils depends on geometry, create_index_spgist, hash_index, brin # ---------- -test: create_table_like alter_generic alter_operator misc async dbsize merge misc_functions sysviews tsrf tid tidscan tidrangescan collate.icu.utf8 incremental_sort create_role +test: create_table_like alter_generic alter_operator misc async dbsize merge misc_functions sysviews tsrf tid tidscan tidrangescan collate.icu.utf8 incremental_sort create_role incremental_matview # collate.*.utf8 tests cannot be run in parallel with each other test: rules psql psql_crosstab amutils stats_ext collate.linux.utf8 collate.windows.win1252 diff --git a/src/test/regress/sql/incremental_matview.sql b/src/test/regress/sql/incremental_matview.sql new file mode 100644 index 0000000000..82686f9324 --- /dev/null +++ b/src/test/regress/sql/incremental_matview.sql @@ -0,0 +1,533 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (i int, j int); +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +CREATE TABLE mv_base_b (i int, k int); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); + +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +REFRESH MATERIALIZED VIEW mv_ivm_1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; + +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; +ROLLBACK; + +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +DROP MATERIALIZED VIEW mv_ivm_rename; + +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +DROP MATERIALIZED VIEW mv_ivm_unique; + +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +ROLLBACK; + +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +ROLLBACK; + +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +ROLLBACK; + +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +ROLLBACK; + +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +ROLLBACK; + +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min; + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); + +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; +ROLLBACK; + +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +SELECT * FROM mv_self ORDER BY v1; +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; +SELECT * FROM mv_self ORDER BY v1; + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + +ROLLBACK; + +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +SELECT * FROM mv ORDER BY v1; +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; +SELECT * FROM mv ORDER BY v1; +ROLLBACK; + +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +SELECT * FROM mv_ri ORDER BY i1; +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; +ROLLBACK; + +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +-- IMMV containing user defined type +BEGIN; + +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); + +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; + +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); + +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); + +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + +ROLLBACK; + +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; + +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; + +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; + +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; + +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; + +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); + +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; + +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); + +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ROLLBACK; + +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; + +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; + +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; + +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; + +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; + +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; + +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); + +-- views containing base tables with Row Level Security +DROP USER IF EXISTS ivm_admin; +DROP USER IF EXISTS ivm_user; +CREATE USER ivm_admin; +CREATE USER ivm_user; + +--- create a table with RLS +SET SESSION AUTHORIZATION ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); + +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; + +--- create a view owned by ivm_user +SET SESSION AUTHORIZATION ivm_user; + +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; +RESET SESSION AUTHORIZATION; + +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'ivm_user' WHERE id = 2) +SELECT; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- +SET SESSION AUTHORIZATION ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +RESET SESSION AUTHORIZATION; + +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + +-- automatic index creation +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); + +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; + +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; + +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; + +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; + +-- cleanup + +DROP TABLE rls_tbl CASCADE; +DROP TABLE num_tbl CASCADE; +DROP USER ivm_user; +DROP USER ivm_admin; + +DROP TABLE mv_base_b CASCADE; +DROP TABLE mv_base_a CASCADE; -- 2.25.1 --Multipart=_Mon__28_Aug_2023_11_52_52_+0900_hj6L5h176QaSGtg7 Content-Type: text/x-diff; name="v29-0011-Add-documentations-about-Incremental-View-Mainte.patch" Content-Disposition: attachment; filename="v29-0011-Add-documentations-about-Incremental-View-Mainte.patch" Content-Transfer-Encoding: 7bit ^ permalink raw reply [nested|flat] 78+ messages in thread
* [PATCH v7 4/7] Row pattern recognition patch (executor). @ 2023-09-22 04:53 Tatsuo Ishii <[email protected]> 0 siblings, 0 replies; 78+ messages in thread From: Tatsuo Ishii @ 2023-09-22 04:53 UTC (permalink / raw) --- src/backend/executor/nodeWindowAgg.c | 853 ++++++++++++++++++++++++++- src/backend/utils/adt/windowfuncs.c | 37 +- src/include/catalog/pg_proc.dat | 6 + src/include/nodes/execnodes.h | 26 + 4 files changed, 909 insertions(+), 13 deletions(-) diff --git a/src/backend/executor/nodeWindowAgg.c b/src/backend/executor/nodeWindowAgg.c index 310ac23e3a..84d1b8acaa 100644 --- a/src/backend/executor/nodeWindowAgg.c +++ b/src/backend/executor/nodeWindowAgg.c @@ -36,6 +36,7 @@ #include "access/htup_details.h" #include "catalog/objectaccess.h" #include "catalog/pg_aggregate.h" +#include "catalog/pg_collation_d.h" #include "catalog/pg_proc.h" #include "executor/executor.h" #include "executor/nodeWindowAgg.h" @@ -48,6 +49,7 @@ #include "utils/acl.h" #include "utils/builtins.h" #include "utils/datum.h" +#include "utils/fmgroids.h" #include "utils/expandeddatum.h" #include "utils/lsyscache.h" #include "utils/memutils.h" @@ -182,8 +184,9 @@ static void begin_partition(WindowAggState *winstate); static void spool_tuples(WindowAggState *winstate, int64 pos); static void release_partition(WindowAggState *winstate); -static int row_is_in_frame(WindowAggState *winstate, int64 pos, +static int row_is_in_frame(WindowAggState *winstate, int64 pos, TupleTableSlot *slot); + static void update_frameheadpos(WindowAggState *winstate); static void update_frametailpos(WindowAggState *winstate); static void update_grouptailpos(WindowAggState *winstate); @@ -195,9 +198,32 @@ static Datum GetAggInitVal(Datum textInitVal, Oid transtype); static bool are_peers(WindowAggState *winstate, TupleTableSlot *slot1, TupleTableSlot *slot2); -static bool window_gettupleslot(WindowObject winobj, int64 pos, - TupleTableSlot *slot); +static int WinGetSlotInFrame(WindowObject winobj, TupleTableSlot *slot, + int relpos, int seektype, bool set_mark, + bool *isnull, bool *isout); +static bool window_gettupleslot(WindowObject winobj, int64 pos, TupleTableSlot *slot); + +static void attno_map(Node *node); +static bool attno_map_walker(Node *node, void *context); +static int row_is_in_reduced_frame(WindowObject winobj, int64 pos); +static bool rpr_is_defined(WindowAggState *winstate); + +static void create_reduced_frame_map(WindowAggState *winstate); +static int get_reduced_frame_map(WindowAggState *winstate, int64 pos); +static void register_reduced_frame_map(WindowAggState *winstate, int64 pos, int val); +static void clear_reduced_frame_map(WindowAggState *winstate); +static void update_reduced_frame(WindowObject winobj, int64 pos); + +static int64 evaluate_pattern(WindowObject winobj, int64 current_pos, + char *vname, StringInfo encoded_str, bool *result); + +static bool get_slots(WindowObject winobj, int64 current_pos); + +static int search_str_set(char *pattern, StringInfo *str_set, int set_size); +static void search_str_set_recurse(char *pattern, StringInfo *str_set, int set_size, int set_index, + int str_index, char *encoded_str, int *resultlen); +static char pattern_initial(WindowAggState *winstate, char *vname); /* * initialize_windowaggregate @@ -673,6 +699,7 @@ eval_windowaggregates(WindowAggState *winstate) WindowObject agg_winobj; TupleTableSlot *agg_row_slot; TupleTableSlot *temp_slot; + bool agg_result_isnull; numaggs = winstate->numaggs; if (numaggs == 0) @@ -778,6 +805,9 @@ eval_windowaggregates(WindowAggState *winstate) * Note that we don't strictly need to restart in the last case, but if * we're going to remove all rows from the aggregation anyway, a restart * surely is faster. + * + * - if RPR is enabled and skip mode is SKIP TO NEXT ROW, + * we restart aggregation too. *---------- */ numaggs_restart = 0; @@ -788,8 +818,11 @@ eval_windowaggregates(WindowAggState *winstate) (winstate->aggregatedbase != winstate->frameheadpos && !OidIsValid(peraggstate->invtransfn_oid)) || (winstate->frameOptions & FRAMEOPTION_EXCLUSION) || - winstate->aggregatedupto <= winstate->frameheadpos) + winstate->aggregatedupto <= winstate->frameheadpos || + (rpr_is_defined(winstate) && + winstate->rpSkipTo == ST_NEXT_ROW)) { + elog(DEBUG1, "peraggstate->restart is set"); peraggstate->restart = true; numaggs_restart++; } @@ -861,8 +894,10 @@ eval_windowaggregates(WindowAggState *winstate) * If we created a mark pointer for aggregates, keep it pushed up to frame * head, so that tuplestore can discard unnecessary rows. */ +#ifdef NOT_USED if (agg_winobj->markptr >= 0) WinSetMarkPosition(agg_winobj, winstate->frameheadpos); +#endif /* * Now restart the aggregates that require it. @@ -917,6 +952,29 @@ eval_windowaggregates(WindowAggState *winstate) { winstate->aggregatedupto = winstate->frameheadpos; ExecClearTuple(agg_row_slot); + + /* + * If RPR is defined, we do not use aggregatedupto_nonrestarted. To + * avoid assertion failure below, we reset aggregatedupto_nonrestarted + * to frameheadpos. + */ + if (rpr_is_defined(winstate)) + aggregatedupto_nonrestarted = winstate->frameheadpos; + } + + agg_result_isnull = false; + /* RPR is defined? */ + if (rpr_is_defined(winstate)) + { + /* + * If the skip mode is SKIP TO PAST LAST ROW and we already know that + * current row is a skipped row, we don't need to accumulate rows, + * just return NULL. Note that for unamtched row, we need to do + * aggregation so that count(*) shows 0, rather than NULL. + */ + if (winstate->rpSkipTo == ST_PAST_LAST_ROW && + get_reduced_frame_map(winstate, winstate->currentpos) == RF_SKIPPED) + agg_result_isnull = true; } /* @@ -930,6 +988,11 @@ eval_windowaggregates(WindowAggState *winstate) { int ret; + elog(DEBUG1, "===== loop in frame starts: " INT64_FORMAT, winstate->aggregatedupto); + + if (agg_result_isnull) + break; + /* Fetch next row if we didn't already */ if (TupIsNull(agg_row_slot)) { @@ -945,9 +1008,28 @@ eval_windowaggregates(WindowAggState *winstate) ret = row_is_in_frame(winstate, winstate->aggregatedupto, agg_row_slot); if (ret < 0) break; + if (ret == 0) goto next_tuple; + if (rpr_is_defined(winstate)) + { + /* + * If the row status at currentpos is already decided and current + * row status is not decided yet, it means we passed the last + * reduced frame. Time to break the loop. + */ + if (get_reduced_frame_map(winstate, winstate->currentpos) != RF_NOT_DETERMINED && + get_reduced_frame_map(winstate, winstate->aggregatedupto) == RF_NOT_DETERMINED) + break; + /* + * Otherwise we need to calculate the reduced frame. + */ + ret = row_is_in_reduced_frame(winstate->agg_winobj, winstate->aggregatedupto); + if (ret == -1) /* unmatched row */ + break; + } + /* Set tuple context for evaluation of aggregate arguments */ winstate->tmpcontext->ecxt_outertuple = agg_row_slot; @@ -976,6 +1058,7 @@ next_tuple: ExecClearTuple(agg_row_slot); } + /* The frame's end is not supposed to move backwards, ever */ Assert(aggregatedupto_nonrestarted <= winstate->aggregatedupto); @@ -996,6 +1079,16 @@ next_tuple: peraggstate, result, isnull); + /* + * RPR is defined and we just return NULL because skip mode is SKIP + * TO PAST LAST ROW and current row is skipped row. + */ + if (agg_result_isnull) + { + *isnull = true; + *result = (Datum) 0; + } + /* * save the result in case next row shares the same frame. * @@ -1090,6 +1183,7 @@ begin_partition(WindowAggState *winstate) winstate->framehead_valid = false; winstate->frametail_valid = false; winstate->grouptail_valid = false; + create_reduced_frame_map(winstate); winstate->spooled_rows = 0; winstate->currentpos = 0; winstate->frameheadpos = 0; @@ -2053,6 +2147,8 @@ ExecWindowAgg(PlanState *pstate) CHECK_FOR_INTERRUPTS(); + elog(DEBUG1, "ExecWindowAgg called. pos: " INT64_FORMAT , winstate->currentpos); + if (winstate->status == WINDOWAGG_DONE) return NULL; @@ -2221,6 +2317,17 @@ ExecWindowAgg(PlanState *pstate) /* don't evaluate the window functions when we're in pass-through mode */ if (winstate->status == WINDOWAGG_RUN) { + /* + * If RPR is defined and skip mode is next row, we need to clear existing + * reduced frame info so that we newly calculate the info starting from + * current row. + */ + if (rpr_is_defined(winstate)) + { + if (winstate->rpSkipTo == ST_NEXT_ROW) + clear_reduced_frame_map(winstate); + } + /* * Evaluate true window functions */ @@ -2388,6 +2495,9 @@ ExecInitWindowAgg(WindowAgg *node, EState *estate, int eflags) TupleDesc scanDesc; ListCell *l; + TargetEntry *te; + Expr *expr; + /* check for unsupported flags */ Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK))); @@ -2483,6 +2593,16 @@ ExecInitWindowAgg(WindowAgg *node, EState *estate, int eflags) winstate->temp_slot_2 = ExecInitExtraTupleSlot(estate, scanDesc, &TTSOpsMinimalTuple); + winstate->prev_slot = ExecInitExtraTupleSlot(estate, scanDesc, + &TTSOpsMinimalTuple); + + winstate->next_slot = ExecInitExtraTupleSlot(estate, scanDesc, + &TTSOpsMinimalTuple); + + winstate->null_slot = ExecInitExtraTupleSlot(estate, scanDesc, + &TTSOpsMinimalTuple); + winstate->null_slot = ExecStoreAllNullTuple(winstate->null_slot); + /* * create frame head and tail slots only if needed (must create slots in * exactly the same cases that update_frameheadpos and update_frametailpos @@ -2667,6 +2787,39 @@ ExecInitWindowAgg(WindowAgg *node, EState *estate, int eflags) winstate->inRangeAsc = node->inRangeAsc; winstate->inRangeNullsFirst = node->inRangeNullsFirst; + /* Set up SKIP TO type */ + winstate->rpSkipTo = node->rpSkipTo; + /* Set up row pattern recognition PATTERN clause */ + winstate->patternVariableList = node->patternVariable; + winstate->patternRegexpList = node->patternRegexp; + + /* Set up row pattern recognition DEFINE clause */ + winstate->defineInitial = node->defineInitial; + winstate->defineVariableList = NIL; + winstate->defineClauseList = NIL; + if (node->defineClause != NIL) + { + /* + * Tweak arg var of PREV/NEXT so that it refers to scan/inner slot. + */ + foreach(l, node->defineClause) + { + char *name; + ExprState *exps; + + te = lfirst(l); + name = te->resname; + expr = te->expr; + + elog(DEBUG1, "defineVariable name: %s", name); + winstate->defineVariableList = lappend(winstate->defineVariableList, + makeString(pstrdup(name))); + attno_map((Node *)expr); + exps = ExecInitExpr(expr, (PlanState *) winstate); + winstate->defineClauseList = lappend(winstate->defineClauseList, exps); + } + } + winstate->all_first = true; winstate->partition_spooled = false; winstate->more_partitions = false; @@ -2674,6 +2827,57 @@ ExecInitWindowAgg(WindowAgg *node, EState *estate, int eflags) return winstate; } +/* + * Rewrite varno of Var node that is the argument of PREV/NET so that it sees + * scan tuple (PREV) or inner tuple (NEXT). + */ +static void +attno_map(Node *node) +{ + (void) expression_tree_walker(node, attno_map_walker, NULL); +} + +static bool +attno_map_walker(Node *node, void *context) +{ + FuncExpr *func; + int nargs; + Expr *expr; + Var *var; + + if (node == NULL) + return false; + + if (IsA(node, FuncExpr)) + { + func = (FuncExpr *)node; + + if (func->funcid == F_PREV || func->funcid == F_NEXT) + { + /* sanity check */ + nargs = list_length(func->args); + if (list_length(func->args) != 1) + elog(ERROR, "PREV/NEXT must have 1 argument but function %d has %d args", func->funcid, nargs); + + expr = (Expr *) lfirst(list_head(func->args)); + if (!IsA(expr, Var)) + elog(ERROR, "PREV/NEXT's arg is not Var"); /* XXX: is it possible that arg type is Const? */ + var = (Var *)expr; + + if (func->funcid == F_PREV) + /* + * Rewrite varno from OUTER_VAR to regular var no so that the + * var references scan tuple. + */ + var->varno = var->varnosyn; + else + var->varno = INNER_VAR; + elog(DEBUG1, "PREV/NEXT's varno is rewritten to: %d", var->varno); + } + } + return expression_tree_walker(node, attno_map_walker, NULL); +} + /* ----------------- * ExecEndWindowAgg * ----------------- @@ -2691,6 +2895,8 @@ ExecEndWindowAgg(WindowAggState *node) ExecClearTuple(node->agg_row_slot); ExecClearTuple(node->temp_slot_1); ExecClearTuple(node->temp_slot_2); + ExecClearTuple(node->prev_slot); + ExecClearTuple(node->next_slot); if (node->framehead_slot) ExecClearTuple(node->framehead_slot); if (node->frametail_slot) @@ -2740,6 +2946,8 @@ ExecReScanWindowAgg(WindowAggState *node) ExecClearTuple(node->agg_row_slot); ExecClearTuple(node->temp_slot_1); ExecClearTuple(node->temp_slot_2); + ExecClearTuple(node->prev_slot); + ExecClearTuple(node->next_slot); if (node->framehead_slot) ExecClearTuple(node->framehead_slot); if (node->frametail_slot) @@ -3100,7 +3308,7 @@ window_gettupleslot(WindowObject winobj, int64 pos, TupleTableSlot *slot) return false; if (pos < winobj->markpos) - elog(ERROR, "cannot fetch row before WindowObject's mark position"); + elog(ERROR, "cannot fetch row: " INT64_FORMAT " before WindowObject's mark position: " INT64_FORMAT, pos, winobj->markpos ); oldcontext = MemoryContextSwitchTo(winstate->ss.ps.ps_ExprContext->ecxt_per_query_memory); @@ -3420,14 +3628,54 @@ WinGetFuncArgInFrame(WindowObject winobj, int argno, WindowAggState *winstate; ExprContext *econtext; TupleTableSlot *slot; - int64 abs_pos; - int64 mark_pos; Assert(WindowObjectIsValid(winobj)); winstate = winobj->winstate; econtext = winstate->ss.ps.ps_ExprContext; slot = winstate->temp_slot_1; + if (WinGetSlotInFrame(winobj, slot, + relpos, seektype, set_mark, + isnull, isout) == 0) + { + econtext->ecxt_outertuple = slot; + return ExecEvalExpr((ExprState *) list_nth(winobj->argstates, argno), + econtext, isnull); + } + + if (isout) + *isout = true; + *isnull = true; + return (Datum) 0; +} + +/* + * WinGetSlotInFrame + * slot: TupleTableSlot to store the result + * relpos: signed rowcount offset from the seek position + * seektype: WINDOW_SEEK_HEAD or WINDOW_SEEK_TAIL + * set_mark: If the row is found/in frame and set_mark is true, the mark is + * moved to the row as a side-effect. + * isnull: output argument, receives isnull status of result + * isout: output argument, set to indicate whether target row position + * is out of frame (can pass NULL if caller doesn't care about this) + * + * Returns 0 if we successfullt got the slot. false if out of frame. + * (also isout is set) + */ +static int +WinGetSlotInFrame(WindowObject winobj, TupleTableSlot *slot, + int relpos, int seektype, bool set_mark, + bool *isnull, bool *isout) +{ + WindowAggState *winstate; + int64 abs_pos; + int64 mark_pos; + int num_reduced_frame; + + Assert(WindowObjectIsValid(winobj)); + winstate = winobj->winstate; + switch (seektype) { case WINDOW_SEEK_CURRENT: @@ -3494,11 +3742,21 @@ WinGetFuncArgInFrame(WindowObject winobj, int argno, winstate->frameOptions); break; } + num_reduced_frame = row_is_in_reduced_frame(winobj, winstate->frameheadpos); + if (num_reduced_frame < 0) + goto out_of_frame; + else if (num_reduced_frame > 0) + if (relpos >= num_reduced_frame) + goto out_of_frame; break; case WINDOW_SEEK_TAIL: /* rejecting relpos > 0 is easy and simplifies code below */ if (relpos > 0) goto out_of_frame; + + /* RPR cares about frame head pos. Need to call update_frameheadpos */ + update_frameheadpos(winstate); + update_frametailpos(winstate); abs_pos = winstate->frametailpos - 1 + relpos; @@ -3565,6 +3823,12 @@ WinGetFuncArgInFrame(WindowObject winobj, int argno, mark_pos = 0; /* keep compiler quiet */ break; } + + num_reduced_frame = row_is_in_reduced_frame(winobj, winstate->frameheadpos + relpos); + if (num_reduced_frame < 0) + goto out_of_frame; + else if (num_reduced_frame > 0) + abs_pos = winstate->frameheadpos + relpos + num_reduced_frame - 1; break; default: elog(ERROR, "unrecognized window seek type: %d", seektype); @@ -3583,15 +3847,13 @@ WinGetFuncArgInFrame(WindowObject winobj, int argno, *isout = false; if (set_mark) WinSetMarkPosition(winobj, mark_pos); - econtext->ecxt_outertuple = slot; - return ExecEvalExpr((ExprState *) list_nth(winobj->argstates, argno), - econtext, isnull); + return 0; out_of_frame: if (isout) *isout = true; *isnull = true; - return (Datum) 0; + return -1; } /* @@ -3622,3 +3884,572 @@ WinGetFuncArgCurrent(WindowObject winobj, int argno, bool *isnull) return ExecEvalExpr((ExprState *) list_nth(winobj->argstates, argno), econtext, isnull); } + +/* + * rpr_is_defined + * return true if Row pattern recognition is defined. + */ +static +bool rpr_is_defined(WindowAggState *winstate) +{ + return winstate->patternVariableList != NIL; +} + +/* + * row_is_in_reduced_frame + * Determine whether a row is in the current row's reduced window frame according + * to row pattern matching + * + * The row must has been already determined that it is in a full window frame + * and fetched it into slot. + * + * Returns: + * = 0, RPR is not defined. + * >0, if the row is the first in the reduced frame. Return the number of rows in the reduced frame. + * -1, if the row is unmatched row + * -2, if the row is in the reduced frame but needed to be skipped because of + * AFTER MATCH SKIP PAST LAST ROW + */ +static +int row_is_in_reduced_frame(WindowObject winobj, int64 pos) +{ + WindowAggState *winstate = winobj->winstate; + int state; + int rtn; + + if (!rpr_is_defined(winstate)) + { + /* + * RPR is not defined. Assume that we are always in the the reduced + * window frame. + */ + rtn = 0; + elog(DEBUG1, "row_is_in_reduced_frame returns %d: pos: " INT64_FORMAT, rtn, pos); + return rtn; + } + + state = get_reduced_frame_map(winstate, pos); + + if (state == RF_NOT_DETERMINED) + { + update_frameheadpos(winstate); + update_reduced_frame(winobj, pos); + } + + state = get_reduced_frame_map(winstate, pos); + + switch (state) + { + int64 i; + int num_reduced_rows; + + case RF_FRAME_HEAD: + num_reduced_rows = 1; + for (i = pos + 1; get_reduced_frame_map(winstate,i) == RF_SKIPPED; i++) + num_reduced_rows++; + rtn = num_reduced_rows; + break; + + case RF_SKIPPED: + rtn = -2; + break; + + case RF_UNMATCHED: + rtn = -1; + break; + + default: + elog(ERROR, "Unrecognized state: %d at: " INT64_FORMAT, state, pos); + break; + } + + elog(DEBUG1, "row_is_in_reduced_frame returns %d: pos: " INT64_FORMAT, rtn, pos); + return rtn; +} + +#define REDUCED_FRAME_MAP_INIT_SIZE 1024L + +/* + * Create reduced frame map + */ +static +void create_reduced_frame_map(WindowAggState *winstate) +{ + winstate->reduced_frame_map = + MemoryContextAlloc(winstate->partcontext, REDUCED_FRAME_MAP_INIT_SIZE); + winstate->alloc_sz = REDUCED_FRAME_MAP_INIT_SIZE; + clear_reduced_frame_map(winstate); +} + +/* + * Clear reduced frame map + */ +static +void clear_reduced_frame_map(WindowAggState *winstate) +{ + Assert(winstate->reduced_frame_map != NULL); + MemSet(winstate->reduced_frame_map, RF_NOT_DETERMINED, + winstate->alloc_sz); +} + +/* + * Get reduced frame map specified by pos + */ +static +int get_reduced_frame_map(WindowAggState *winstate, int64 pos) +{ + Assert(winstate->reduced_frame_map != NULL); + + if (pos < 0 || pos >= winstate->alloc_sz) + elog(ERROR, "wrong pos: " INT64_FORMAT, pos); + + return winstate->reduced_frame_map[pos]; +} + +/* + * Add/replace reduced frame map member at pos. + * If there's no enough space, expand the map. + */ +static +void register_reduced_frame_map(WindowAggState *winstate, int64 pos, int val) +{ + int64 realloc_sz; + + Assert(winstate->reduced_frame_map != NULL); + + if (pos < 0) + elog(ERROR, "wrong pos: " INT64_FORMAT, pos); + + if (pos > winstate->alloc_sz - 1) + { + realloc_sz = winstate->alloc_sz * 2; + + winstate->reduced_frame_map = + repalloc(winstate->reduced_frame_map, realloc_sz); + + MemSet(winstate->reduced_frame_map + winstate->alloc_sz, + RF_NOT_DETERMINED, realloc_sz - winstate->alloc_sz); + + winstate->alloc_sz = realloc_sz; + } + + winstate->reduced_frame_map[pos] = val; +} + +/* + * update_reduced_frame + * Update reduced frame info. + */ +static +void update_reduced_frame(WindowObject winobj, int64 pos) +{ + WindowAggState *winstate = winobj->winstate; + ListCell *lc1, *lc2; + bool expression_result; + int num_matched_rows; + int64 original_pos; + bool anymatch; + StringInfo encoded_str; + StringInfo pattern_str = makeStringInfo(); + + /* + * Array of pattern variables evaluted to true. + * Each character corresponds to pattern variable. + * Example: + * str_set[0] = "AB"; + * str_set[1] = "AC"; + * In this case at row 0 A and B are true, and A and C are true in row 1. + */ + #define ENCODED_STR_ARRAY_ALLOC_SIZE 128 + StringInfo *str_set = NULL; + int str_set_index; + int str_set_size; + + /* save original pos */ + original_pos = pos; + + /* + * Loop over until none of pattern matches or encounters end of frame. + */ + for (;;) + { + int64 result_pos = -1; + + /* + * Loop over each PATTERN variable. + */ + anymatch = false; + encoded_str = makeStringInfo(); + + forboth(lc1, winstate->patternVariableList, lc2, winstate->patternRegexpList) + { + char *vname = strVal(lfirst(lc1)); + char *quantifier = strVal(lfirst(lc2)); + + elog(DEBUG1, "pos: " INT64_FORMAT " pattern vname: %s quantifier: %s", pos, vname, quantifier); + + expression_result = false; + + /* evaluate row pattern against current row */ + result_pos = evaluate_pattern(winobj, pos, vname, encoded_str, &expression_result); + if (expression_result) + { + elog(DEBUG1, "expression result is true"); + anymatch = true; + } + + /* + * If out of frame, we are done. + */ + if (result_pos < 0) + break; + } + + if (!anymatch) + { + /* none of patterns matched. */ + break; + } + + /* build encoded string array */ + if (str_set == NULL) + { + str_set_index = 0; + str_set_size = ENCODED_STR_ARRAY_ALLOC_SIZE * sizeof(StringInfo); + str_set = palloc(str_set_size); + } + + str_set[str_set_index++] = encoded_str; + + elog(DEBUG1, "pos: " INT64_FORMAT " str_set_index: %d encoded_str: %s", pos, str_set_index, encoded_str->data); + + if (str_set_index >= str_set_size) + { + str_set_size *= 2; + str_set = repalloc(str_set, str_set_size); + } + + /* move to next row */ + pos++; + + if (result_pos < 0) + { + /* out of frame */ + break; + } + } + + if (str_set == NULL) + { + /* no match found in the first row */ + register_reduced_frame_map(winstate, original_pos, RF_UNMATCHED); + return; + } + + elog(DEBUG2, "pos: " INT64_FORMAT " encoded_str: %s", pos, encoded_str->data); + + /* build regular expression */ + pattern_str = makeStringInfo(); + appendStringInfoChar(pattern_str, '^'); + forboth (lc1, winstate->patternVariableList, lc2, winstate->patternRegexpList) + { + char *vname = strVal(lfirst(lc1)); + char *quantifier = strVal(lfirst(lc2)); + char initial; + + initial = pattern_initial(winstate, vname); + Assert(initial != 0); + appendStringInfoChar(pattern_str, initial); + if (quantifier[0]) + appendStringInfoChar(pattern_str, quantifier[0]); + elog(DEBUG1, "vname: %s initial: %c quantifier: %s", vname, initial, quantifier); + } + + elog(DEBUG2, "pos: " INT64_FORMAT " pattern: %s", pos, pattern_str->data); + + /* look for matching pattern variable sequence */ + num_matched_rows = search_str_set(pattern_str->data, str_set, str_set_index); + /* + * We are at the first row in the reduced frame. Save the number of + * matched rows as the number of rows in the reduced frame. + */ + if (num_matched_rows <= 0) + { + /* no match */ + register_reduced_frame_map(winstate, original_pos, RF_UNMATCHED); + } + else + { + int64 i; + + register_reduced_frame_map(winstate, original_pos, RF_FRAME_HEAD); + + for (i = original_pos + 1; i < original_pos + num_matched_rows; i++) + { + register_reduced_frame_map(winstate, i, RF_SKIPPED); + } + } + + return; +} + +/* + * Perform regex search pattern against encoded string array str_set. + * returns the number of longest matching rows. + * str_set: array of encoded string. Each array element corresponds to each + * row. + * set_size: size of set_str array. + */ +static +int search_str_set(char *pattern, StringInfo *str_set, int set_size) +{ + char *encoded_str = palloc0(set_size+1); + int resultlen = 0; + + search_str_set_recurse(pattern, str_set, set_size, 0, 0, + encoded_str, &resultlen); + elog(DEBUG1, "search_str_set returns %d", resultlen); + return resultlen; +} + +/* + * Workhorse of search_str_set. + * + * Recurse among matched pattern variables in a row. The max recursion depth + * is number of pattern variables matched in a row. + */ +static +void search_str_set_recurse(char *pattern, StringInfo *str_set, + int set_size, int set_index, int str_index, + char *encoded_str, int *resultlen) +{ + for (;;) + { + char c; + + c = str_set[set_index]->data[str_index]; + if (c == '\0') + return; + encoded_str[set_index] = c; + set_index++; + + if (set_index >= set_size) + { + Datum d; + text *res; + char *substr; + + /* + * We first perform pattern matching using regexp_instr, then call + * textregexsubstr to get matched substring to know how long the + * matched string is. That is the number of rows in the reduced window + * frame. The reason why we can't call textregexsubstr in the first + * place is, it errors out if pattern does not match. + */ + if (DatumGetInt32(DirectFunctionCall2Coll(regexp_instr, DEFAULT_COLLATION_OID, + PointerGetDatum(cstring_to_text(encoded_str)), + PointerGetDatum(cstring_to_text(pattern)))) > 0) + { + d = DirectFunctionCall2Coll(textregexsubstr, + DEFAULT_COLLATION_OID, + PointerGetDatum(cstring_to_text(encoded_str)), + PointerGetDatum(cstring_to_text(pattern))); + if (d != 0) + { + int len; + + res = DatumGetTextPP(d); + substr = text_to_cstring(res); + len = strlen(substr); + if (len > *resultlen) + /* remember the longest match */ + *resultlen = len; + } + } + return; + } + else + search_str_set_recurse(pattern, str_set, set_size, set_index, str_index + 1, + encoded_str, resultlen); + } +} + +/* + * Evaluate expression associated with PATTERN variable vname. + * relpos is relative row position in a frame (starting from 0). + * "quantifier" is the quatifier part of the PATTERN regular expression. + * Currently only '+' is allowed. + * result is out paramater representing the expression evaluation result + * is true of false. + * Return values are: + * >=0: the last match absolute row position + * other wise out of frame. + */ +static +int64 evaluate_pattern(WindowObject winobj, int64 current_pos, + char *vname, StringInfo encoded_str, bool *result) +{ + WindowAggState *winstate = winobj->winstate; + ExprContext *econtext = winstate->ss.ps.ps_ExprContext; + ListCell *lc1, *lc2, *lc3; + ExprState *pat; + Datum eval_result; + bool out_of_frame = false; + bool isnull; + + forthree (lc1, winstate->defineVariableList, lc2, winstate->defineClauseList, lc3, winstate->defineInitial) + { + char initial; + char *name = strVal(lfirst(lc1)); + + if (strcmp(vname, name)) + continue; + + initial = *(strVal(lfirst(lc3))); + + /* set expression to evaluate */ + pat = lfirst(lc2); + + /* get current, previous and next tuples */ + if (!get_slots(winobj, current_pos)) + { + out_of_frame = true; + } + else + { + /* evaluate the expression */ + eval_result = ExecEvalExpr(pat, econtext, &isnull); + if (isnull) + { + /* expression is NULL */ + elog(DEBUG1, "expression for %s is NULL at row: " INT64_FORMAT, vname, current_pos); + *result = false; + } + else + { + if (!DatumGetBool(eval_result)) + { + /* expression is false */ + elog(DEBUG1, "expression for %s is false at row: " INT64_FORMAT, vname, current_pos); + *result = false; + } + else + { + /* expression is true */ + elog(DEBUG1, "expression for %s is true at row: " INT64_FORMAT, vname, current_pos); + appendStringInfoChar(encoded_str, initial); + *result = true; + } + } + break; + } + + if (out_of_frame) + { + *result = false; + return -1; + } + } + return current_pos; +} + +/* + * Get current, previous and next tuples. + * Returns false if current row is out of partition/full frame. + */ +static +bool get_slots(WindowObject winobj, int64 current_pos) +{ + WindowAggState *winstate = winobj->winstate; + TupleTableSlot *slot; + int ret; + ExprContext *econtext; + + econtext = winstate->ss.ps.ps_ExprContext; + + /* set up current row tuple slot */ + slot = winstate->temp_slot_1; + if (!window_gettupleslot(winobj, current_pos, slot)) + { + elog(DEBUG1, "current row is out of partition at:" INT64_FORMAT, current_pos); + return false; + + ret = row_is_in_frame(winstate, current_pos, slot); + if (ret <= 0) + { + elog(DEBUG1, "current row is out of frame at: " INT64_FORMAT, current_pos); + return false; + } + } + econtext->ecxt_outertuple = slot; + + /* for PREV */ + if (current_pos > 0) + { + slot = winstate->prev_slot; + if (!window_gettupleslot(winobj, current_pos - 1, slot)) + { + elog(DEBUG1, "previous row is out of partition at: " INT64_FORMAT, current_pos - 1); + econtext->ecxt_scantuple = winstate->null_slot; + } + else + { + ret = row_is_in_frame(winstate, current_pos - 1, slot); + if (ret <= 0) + { + elog(DEBUG1, "previous row is out of frame at: " INT64_FORMAT, current_pos - 1); + econtext->ecxt_scantuple = winstate->null_slot; + } + else + { + econtext->ecxt_scantuple = slot; + } + } + } + else + econtext->ecxt_scantuple = winstate->null_slot; + + /* for NEXT */ + slot = winstate->next_slot; + if (!window_gettupleslot(winobj, current_pos + 1, slot)) + { + elog(DEBUG1, "next row is out of partiton at: " INT64_FORMAT, current_pos + 1); + econtext->ecxt_innertuple = winstate->null_slot; + } + else + { + ret = row_is_in_frame(winstate, current_pos + 1, slot); + if (ret <= 0) + { + elog(DEBUG1, "next row is out of frame at: " INT64_FORMAT, current_pos + 1); + econtext->ecxt_innertuple = winstate->null_slot; + } + else + econtext->ecxt_innertuple = slot; + } + return true; +} + +/* + * Return pattern variable initial character + * matching with pattern variable name vname. + * If not found, return 0. + */ +static +char pattern_initial(WindowAggState *winstate, char *vname) +{ + char initial; + char *name; + ListCell *lc1, *lc2; + + forboth (lc1, winstate->defineVariableList, lc2, winstate->defineInitial) + { + name = strVal(lfirst(lc1)); /* DEFINE variable name */ + initial = *(strVal(lfirst(lc2))); /* DEFINE variable initial */ + + + if (!strcmp(name, vname)) + return initial; /* found */ + } + return 0; +} diff --git a/src/backend/utils/adt/windowfuncs.c b/src/backend/utils/adt/windowfuncs.c index b87a624fb2..9ebcc7b5d2 100644 --- a/src/backend/utils/adt/windowfuncs.c +++ b/src/backend/utils/adt/windowfuncs.c @@ -13,6 +13,9 @@ */ #include "postgres.h" +#include "catalog/pg_collation_d.h" +#include "executor/executor.h" +#include "nodes/execnodes.h" #include "nodes/supportnodes.h" #include "utils/builtins.h" #include "windowapi.h" @@ -36,11 +39,19 @@ typedef struct int64 remainder; /* (total rows) % (bucket num) */ } ntile_context; +/* + * rpr process information. + * Used for AFTER MATCH SKIP PAST LAST ROW + */ +typedef struct SkipContext +{ + int64 pos; /* last row absolute position */ +} SkipContext; + static bool rank_up(WindowObject winobj); static Datum leadlag_common(FunctionCallInfo fcinfo, bool forward, bool withoffset, bool withdefault); - /* * utility routine for *_rank functions. */ @@ -673,7 +684,7 @@ window_last_value(PG_FUNCTION_ARGS) bool isnull; result = WinGetFuncArgInFrame(winobj, 0, - 0, WINDOW_SEEK_TAIL, true, + 0, WINDOW_SEEK_TAIL, false, &isnull, NULL); if (isnull) PG_RETURN_NULL(); @@ -713,3 +724,25 @@ window_nth_value(PG_FUNCTION_ARGS) PG_RETURN_DATUM(result); } + +/* + * prev + * Dummy function to invoke RPR's navigation operator "PREV". + * This is *not* a window function. + */ +Datum +window_prev(PG_FUNCTION_ARGS) +{ + PG_RETURN_DATUM(PG_GETARG_DATUM(0)); +} + +/* + * next + * Dummy function to invoke RPR's navigation operation "NEXT". + * This is *not* a window function. + */ +Datum +window_next(PG_FUNCTION_ARGS) +{ + PG_RETURN_DATUM(PG_GETARG_DATUM(0)); +} diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat index 9805bc6118..d20f803cf5 100644 --- a/src/include/catalog/pg_proc.dat +++ b/src/include/catalog/pg_proc.dat @@ -10416,6 +10416,12 @@ { oid => '3114', descr => 'fetch the Nth row value', proname => 'nth_value', prokind => 'w', prorettype => 'anyelement', proargtypes => 'anyelement int4', prosrc => 'window_nth_value' }, +{ oid => '6122', descr => 'previous value', + proname => 'prev', provolatile => 's', prorettype => 'anyelement', + proargtypes => 'anyelement', prosrc => 'window_prev' }, +{ oid => '6123', descr => 'next value', + proname => 'next', provolatile => 's', prorettype => 'anyelement', + proargtypes => 'anyelement', prosrc => 'window_next' }, # functions for range types { oid => '3832', descr => 'I/O', diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h index cb714f4a19..63feb68f60 100644 --- a/src/include/nodes/execnodes.h +++ b/src/include/nodes/execnodes.h @@ -2471,6 +2471,11 @@ typedef enum WindowAggStatus * tuples during spool */ } WindowAggStatus; +#define RF_NOT_DETERMINED 0 +#define RF_FRAME_HEAD 1 +#define RF_SKIPPED 2 +#define RF_UNMATCHED 3 + typedef struct WindowAggState { ScanState ss; /* its first field is NodeTag */ @@ -2519,6 +2524,15 @@ typedef struct WindowAggState int64 groupheadpos; /* current row's peer group head position */ int64 grouptailpos; /* " " " " tail position (group end+1) */ + /* these fields are used in Row pattern recognition: */ + RPSkipTo rpSkipTo; /* Row Pattern Skip To type */ + List *patternVariableList; /* list of row pattern variables names (list of String) */ + List *patternRegexpList; /* list of row pattern regular expressions ('+' or ''. list of String) */ + List *defineVariableList; /* list of row pattern definition variables (list of String) */ + List *defineClauseList; /* expression for row pattern definition + * search conditions ExprState list */ + List *defineInitial; /* list of row pattern definition variable initials (list of String) */ + MemoryContext partcontext; /* context for partition-lifespan data */ MemoryContext aggcontext; /* shared context for aggregate working data */ MemoryContext curaggcontext; /* current aggregate's working data */ @@ -2555,6 +2569,18 @@ typedef struct WindowAggState TupleTableSlot *agg_row_slot; TupleTableSlot *temp_slot_1; TupleTableSlot *temp_slot_2; + + /* temporary slots for RPR */ + TupleTableSlot *prev_slot; /* PREV row navigation operator */ + TupleTableSlot *next_slot; /* NEXT row navigation operator */ + TupleTableSlot *null_slot; /* all NULL slot */ + + /* + * Each byte corresponds to a row positioned at absolute its pos in + * partition. See above definition for RF_* + */ + char *reduced_frame_map; + int64 alloc_sz; /* size of the map */ } WindowAggState; /* ---------------- -- 2.25.1 ----Next_Part(Fri_Sep_22_14_16_40_2023_530)-- Content-Type: Text/X-Patch; charset=us-ascii Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="v7-0005-Row-pattern-recognition-patch-docs.patch" ^ permalink raw reply [nested|flat] 78+ messages in thread
* [PATCH v37 10/11] Add regression tests for Incremental View Maintenance @ 2026-05-29 09:31 Yugo Nagata <[email protected]> 0 siblings, 0 replies; 78+ messages in thread From: Yugo Nagata @ 2026-05-29 09:31 UTC (permalink / raw) --- src/test/isolation/isolation_schedule | 9 + .../regress/expected/incremental_matview.out | 1100 +++++++++++++++++ src/test/regress/parallel_schedule | 1 + src/test/regress/sql/incremental_matview.sql | 580 +++++++++ 4 files changed, 1690 insertions(+) create mode 100644 src/test/regress/expected/incremental_matview.out create mode 100644 src/test/regress/sql/incremental_matview.sql diff --git a/src/test/isolation/isolation_schedule b/src/test/isolation/isolation_schedule index 15c33fad4c5..111fd465207 100644 --- a/src/test/isolation/isolation_schedule +++ b/src/test/isolation/isolation_schedule @@ -127,3 +127,12 @@ test: matview-write-skew test: lock-nowait test: for-portion-of test: ddl-dependency-locking +test: ivm-create-insert +test: ivm-create-insert2 +test: ivm-create-insert3 +test: ivm-insert-insert +test: ivm-insert-insert2 +test: ivm-insert-insert3 +test: ivm-refresh-insert +test: ivm-refresh-insert2 +test: ivm-refresh-insert3 diff --git a/src/test/regress/expected/incremental_matview.out b/src/test/regress/expected/incremental_matview.out new file mode 100644 index 00000000000..f215aa88e48 --- /dev/null +++ b/src/test/regress/expected/incremental_matview.out @@ -0,0 +1,1100 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ERROR: materialized view "mv_ivm_1" has not been populated +HINT: Use the REFRESH MATERIALIZED VIEW command. +REFRESH MATERIALIZED VIEW mv_ivm_1; +NOTICE: could not create an index on materialized view "mv_ivm_1" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 17 +(1 row) + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 1 +(1 row) + +ROLLBACK; +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_rename_index" on materialized view "mv_ivm_rename" +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +ERROR: IVM column can not be renamed +DROP MATERIALIZED VIEW mv_ivm_rename; +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_unique_index" on materialized view "mv_ivm_unique" +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +ERROR: unique index creation on IVM columns is not supported +DROP MATERIALIZED VIEW mv_ivm_unique; +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +NOTICE: could not create an index on materialized view "mv_ivm_func" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +NOTICE: could not create an index on materialized view "mv_ivm_no_tbl" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_duplicate" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +NOTICE: created index "mv_ivm_distinct_index" on materialized view "mv_ivm_distinct" +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 20 + 30 + 40 + 50 +(6 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +ROLLBACK; +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 120 | 2 | 60.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+---------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 220 | 2 | 110.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 20 | 1 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 120 | 2 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; + sum | count +-----+------- +(0 rows) + +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; + i | sum | count +---+-----+------- +(0 rows) + +ROLLBACK; +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 150 | 5 | 30.0000000000000000 +(1 row) + +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 210 | 6 | 35.0000000000000000 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +NOTICE: created index "mv_ivm_avg_bug_index" on materialized view "mv_ivm_avg_bug" +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 3 | 3.3333333333333333 + 2 | 80 | 3 | 26.6666666666666667 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_min_max_index" on materialized view "mv_ivm_min_max" +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 10 + 2 | 20 | 20 + 3 | 30 | 30 + 4 | 40 | 40 + 5 | 50 | 50 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 12 + 2 | 20 | 22 + 3 | 30 | 32 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 11 | 12 + 2 | 20 | 22 + 3 | 30 | 31 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min_max" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 50 +(1 row) + +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 0 | 70 +(1 row) + +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 60 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + | +(1 row) + +ROLLBACK; +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min; + min +----- + 10 +(1 row) + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + min +----- + 20 +(1 row) + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; + min +----- + 30 +(1 row) + +ROLLBACK; +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | sum +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | b +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ERROR: too many column names were specified +ROLLBACK; +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +NOTICE: could not create an index on materialized view "mv_self" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +----+---- + 10 | 10 + 20 | 20 + 30 | 30 +(3 rows) + +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 30 | 30 + 40 | 40 + 200 | 200 +(3 rows) + +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 130 | 130 + 300 | 300 +(4 rows) + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 70 | 70 + 70 | 77 + 77 | 70 + 77 | 77 + 130 | 130 + 300 | 300 +(8 rows) + +ROLLBACK; +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY v1; + v1 | v2 +----+----- + 10 | 100 + 20 | 200 + 30 | 300 +(3 rows) + +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv ORDER BY v1; + v1 | v2 +------+----- + 10 | 100 + 11 | 100 + 1020 | 200 + 1020 | 222 +(4 rows) + +ROLLBACK; +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +NOTICE: created index "mv_ri_index" on materialized view "mv_ri" +SELECT * FROM mv_ri ORDER BY i1; + i1 | i2 +----+---- + 1 | 1 + 2 | 2 + 3 | 3 +(3 rows) + +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; + i1 | i2 +----+---- + 3 | 3 + 10 | 10 +(2 rows) + +ROLLBACK; +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | +(2 rows) + +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | 20 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i +--- +(0 rows) + +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; + i +--- + 1 + +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 30 + | 3 +(2 rows) + +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 300 + | 30 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 1 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 4 +(1 row) + +ROLLBACK; +-- IMMV containing user defined type +BEGIN; +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: return type mytype is only a shell +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: argument type mytype is only a shell +LINE 1: CREATE FUNCTION mytype_out(mytype) + ^ +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +NOTICE: could not create an index on materialized view "mv_mytype" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + x +--- + 1 +(1 row) + +ROLLBACK; +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +ERROR: OUTER JOIN is not supported on incrementally maintainable materialized view +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +ERROR: CTE is not supported on incrementally maintainable materialized view +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +ERROR: ORDER BY clause is not supported on incrementally maintainable materialized view +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; +ERROR: HAVING clause is not supported on incrementally maintainable materialized view +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; +ERROR: mutable function is not supported on incrementally maintainable materialized view +HINT: functions must be marked IMMUTABLE +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; +ERROR: LIMIT/OFFSET clause is not supported on incrementally maintainable materialized view +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; +ERROR: DISTINCT ON is not supported on incrementally maintainable materialized view +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); +ERROR: TABLESAMPLE clause is not supported on incrementally maintainable materialized view +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; +ERROR: window functions are not supported on incrementally maintainable materialized view +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +ERROR: aggregate function with FILTER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +ERROR: aggregate function with DISTINCT arguments is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +ERROR: aggregate function with ORDER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); +ERROR: GROUPING SETS, ROLLUP, or CUBE clauses is not supported on incrementally maintainable materialized view +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ERROR: inheritance parent is not supported on incrementally maintainable materialized view +ROLLBACK; +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; +ERROR: UNION/INTERSECT/EXCEPT statements are not supported on incrementally maintainable materialized view +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; +ERROR: empty target list is not supported on incrementally maintainable materialized view +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; +ERROR: FOR UPDATE/SHARE clause is not supported on incrementally maintainable materialized view +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; +ERROR: column name __ivm_count__ is not supported on incrementally maintainable materialized view +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; +ERROR: GROUP BY expression not appearing in select list is not supported on incrementally maintainable materialized view +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); +ERROR: VALUES is not supported on incrementally maintainable materialized view +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +NOTICE: role "regress_ivm_admin" does not exist, skipping +DROP USER IF EXISTS regress_ivm_user; +NOTICE: role "regress_ivm_user" does not exist, skipping +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +NOTICE: could not create an index on materialized view "ivm_rls" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user +(1 row) + +RESET SESSION AUTHORIZATION; +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user + 3 | baz | regress_ivm_user +(2 rows) + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +-- +(1 row) + +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+-------+------------------ + 2 | bar | regress_ivm_user + 3 | baz | regress_ivm_user + 6 | corge | regress_ivm_user +(3 rows) + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +NOTICE: could not create an index on materialized view "ivm_rls2" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +RESET SESSION AUTHORIZATION; +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +-- +(1 row) + +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + id | data | owner | num +----+-------+------------------+--------- + 2 | bar | regress_ivm_user | two + 3 | baz_2 | regress_ivm_user | three_2 + 6 | corge | regress_ivm_user | six +(3 rows) + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +NOTICE: could not create an index on materialized view "mv_update_same" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + i +--- + 2 +(1 row) + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +NOTICE: created index "mv_self_ref_index" on materialized view "mv_self_ref" +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; + a | b +----+---- + 11 | + 12 | 11 + 13 | 12 +(3 rows) + +ROLLBACK; +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; +NOTICE: created index "mv_idx1_index" on materialized view "mv_idx1" +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; +NOTICE: created index "mv_idx2_index" on materialized view "mv_idx2" +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; +NOTICE: created index "mv_idx3_index" on materialized view "mv_idx3" +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +NOTICE: could not create an index on materialized view "mv_idx4" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; +NOTICE: could not create an index on materialized view "mv_idx5" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); +NOTICE: could not create an index on materialized view "mv_idx6" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ERROR: data type json has no default operator class for access method "btree" +ROLLBACK; +-- cleanup +DROP TABLE rls_tbl CASCADE; +NOTICE: drop cascades to 2 other objects +DETAIL: drop cascades to materialized view ivm_rls +drop cascades to materialized view ivm_rls2 +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; +DROP TABLE mv_base_b CASCADE; +NOTICE: drop cascades to 3 other objects +DETAIL: drop cascades to materialized view mv_ivm_1 +drop cascades to view b_view +drop cascades to materialized view b_mview +DROP TABLE mv_base_a CASCADE; diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index 8fa0a6c47fb..7caca5f64fd 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -77,6 +77,7 @@ test: brin_bloom brin_multi # Another group of parallel tests # ---------- test: create_table_like alter_generic alter_operator misc async dbsize merge misc_functions nls sysviews tsrf tid tidscan tidrangescan collate.utf8 collate.icu.utf8 incremental_sort create_role without_overlaps generated_virtual +test: incremental_matview # collate.linux.utf8 and collate.icu.utf8 tests cannot be run in parallel with each other # psql depends on create_am diff --git a/src/test/regress/sql/incremental_matview.sql b/src/test/regress/sql/incremental_matview.sql new file mode 100644 index 00000000000..2d55c393d6f --- /dev/null +++ b/src/test/regress/sql/incremental_matview.sql @@ -0,0 +1,580 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); + +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +REFRESH MATERIALIZED VIEW mv_ivm_1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; + +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; +ROLLBACK; + +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +DROP MATERIALIZED VIEW mv_ivm_rename; + +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +DROP MATERIALIZED VIEW mv_ivm_unique; + +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; + + +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +ROLLBACK; + +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +ROLLBACK; + +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +ROLLBACK; + +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +ROLLBACK; + +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +ROLLBACK; + +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min; + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); + +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; +ROLLBACK; + +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +SELECT * FROM mv_self ORDER BY v1; +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; +SELECT * FROM mv_self ORDER BY v1; + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + +ROLLBACK; + +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +SELECT * FROM mv ORDER BY v1; +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; +SELECT * FROM mv ORDER BY v1; +ROLLBACK; + +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +SELECT * FROM mv_ri ORDER BY i1; +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; +ROLLBACK; + +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +-- IMMV containing user defined type +BEGIN; + +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); + +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; + +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); + +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); + +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + +ROLLBACK; + +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; + +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; + +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; + +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; + +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; + +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); + +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; + +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); + +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ROLLBACK; + +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; + +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; + +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; + +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; + +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; + +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; + +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); + +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +DROP USER IF EXISTS regress_ivm_user; +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; + +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); + +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; + +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; + +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; +RESET SESSION AUTHORIZATION; + +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +RESET SESSION AUTHORIZATION; + +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; +ROLLBACK; + +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); + +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; + +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; + +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; + +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; + +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); + +ROLLBACK; + +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ROLLBACK; + +-- cleanup + +DROP TABLE rls_tbl CASCADE; +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; + +DROP TABLE mv_base_b CASCADE; +DROP TABLE mv_base_a CASCADE; -- 2.43.0 --Multipart=_Fri__29_May_2026_23_14_17_+0900_Te0o73X2VqYK57Gd Content-Type: text/x-diff; name="v37-0009-Add-support-for-min-max-aggregates-for-IVM.patch" Content-Disposition: attachment; filename="v37-0009-Add-support-for-min-max-aggregates-for-IVM.patch" Content-Transfer-Encoding: 7bit ^ permalink raw reply [nested|flat] 78+ messages in thread
* [PATCH v39 7/8] Add regression tests for Incremental View Maintenance @ 2026-05-29 09:31 Yugo Nagata <[email protected]> 0 siblings, 0 replies; 78+ messages in thread From: Yugo Nagata @ 2026-05-29 09:31 UTC (permalink / raw) --- .../isolation/expected/ivm-create-insert.out | 285 ++++++++ .../isolation/expected/ivm-create-insert2.out | 305 ++++++++ .../isolation/expected/ivm-create-insert3.out | 305 ++++++++ .../isolation/expected/ivm-insert-insert.out | 497 +++++++++++++ .../isolation/expected/ivm-insert-insert2.out | 373 ++++++++++ .../isolation/expected/ivm-insert-insert3.out | 373 ++++++++++ .../isolation/expected/ivm-refresh-insert.out | 213 ++++++ .../expected/ivm-refresh-insert2.out | 191 +++++ .../expected/ivm-refresh-insert3.out | 191 +++++ src/test/isolation/isolation_schedule | 9 + .../isolation/specs/ivm-create-insert.spec | 47 ++ .../isolation/specs/ivm-create-insert2.spec | 54 ++ .../isolation/specs/ivm-create-insert3.spec | 54 ++ .../isolation/specs/ivm-insert-insert.spec | 62 ++ .../isolation/specs/ivm-insert-insert2.spec | 62 ++ .../isolation/specs/ivm-insert-insert3.spec | 62 ++ .../isolation/specs/ivm-refresh-insert.spec | 46 ++ .../isolation/specs/ivm-refresh-insert2.spec | 46 ++ .../isolation/specs/ivm-refresh-insert3.spec | 46 ++ .../regress/expected/incremental_matview.out | 667 ++++++++++++++++++ src/test/regress/parallel_schedule | 1 + src/test/regress/sql/incremental_matview.sql | 407 +++++++++++ 22 files changed, 4296 insertions(+) create mode 100644 src/test/isolation/expected/ivm-create-insert.out create mode 100644 src/test/isolation/expected/ivm-create-insert2.out create mode 100644 src/test/isolation/expected/ivm-create-insert3.out create mode 100644 src/test/isolation/expected/ivm-insert-insert.out create mode 100644 src/test/isolation/expected/ivm-insert-insert2.out create mode 100644 src/test/isolation/expected/ivm-insert-insert3.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert2.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert3.out create mode 100644 src/test/isolation/specs/ivm-create-insert.spec create mode 100644 src/test/isolation/specs/ivm-create-insert2.spec create mode 100644 src/test/isolation/specs/ivm-create-insert3.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert2.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert3.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert2.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert3.spec create mode 100644 src/test/regress/expected/incremental_matview.out create mode 100644 src/test/regress/sql/incremental_matview.sql diff --git a/src/test/isolation/expected/ivm-create-insert.out b/src/test/isolation/expected/ivm-create-insert.out new file mode 100644 index 00000000000..5da00043aba --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert.out @@ -0,0 +1,285 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-create-insert2.out b/src/test/isolation/expected/ivm-create-insert2.out new file mode 100644 index 00000000000..907d892c6d4 --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert2.out @@ -0,0 +1,305 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + diff --git a/src/test/isolation/expected/ivm-create-insert3.out b/src/test/isolation/expected/ivm-create-insert3.out new file mode 100644 index 00000000000..907d892c6d4 --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert3.out @@ -0,0 +1,305 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert.out b/src/test/isolation/expected/ivm-insert-insert.out new file mode 100644 index 00000000000..5ca4cfea677 --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert.out @@ -0,0 +1,497 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; <waiting ...> +step c1: COMMIT; +step update2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; <waiting ...> +step c1: COMMIT; +step update2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; <waiting ...> +step c2: COMMIT; +step update1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; <waiting ...> +step c2: COMMIT; +step update1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); <waiting ...> +step c1: COMMIT; +step insert2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); <waiting ...> +step c1: COMMIT; +step insert2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); <waiting ...> +step c2: COMMIT; +step insert1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); <waiting ...> +step c2: COMMIT; +step insert1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert2.out b/src/test/isolation/expected/ivm-insert-insert2.out new file mode 100644 index 00000000000..e1c66d4de5e --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert2.out @@ -0,0 +1,373 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert3.out b/src/test/isolation/expected/ivm-insert-insert3.out new file mode 100644 index 00000000000..e1c66d4de5e --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert3.out @@ -0,0 +1,373 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert.out b/src/test/isolation/expected/ivm-refresh-insert.out new file mode 100644 index 00000000000..a925938bf1c --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert.out @@ -0,0 +1,213 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert2.out b/src/test/isolation/expected/ivm-refresh-insert2.out new file mode 100644 index 00000000000..dc1b16ae34e --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert2.out @@ -0,0 +1,191 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert3.out b/src/test/isolation/expected/ivm-refresh-insert3.out new file mode 100644 index 00000000000..dc1b16ae34e --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert3.out @@ -0,0 +1,191 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/isolation_schedule b/src/test/isolation/isolation_schedule index b8ebe92553c..6b7e873b370 100644 --- a/src/test/isolation/isolation_schedule +++ b/src/test/isolation/isolation_schedule @@ -128,3 +128,12 @@ test: matview-write-skew test: lock-nowait test: for-portion-of test: ddl-dependency-locking +test: ivm-create-insert +test: ivm-create-insert2 +test: ivm-create-insert3 +test: ivm-insert-insert +test: ivm-insert-insert2 +test: ivm-insert-insert3 +test: ivm-refresh-insert +test: ivm-refresh-insert2 +test: ivm-refresh-insert3 diff --git a/src/test/isolation/specs/ivm-create-insert.spec b/src/test/isolation/specs/ivm-create-insert.spec new file mode 100644 index 00000000000..ccd6fd080a9 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert.spec @@ -0,0 +1,47 @@ +# Test interaction between concurrent transactions performing +# create and insert in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-create-insert2.spec b/src/test/isolation/specs/ivm-create-insert2.spec new file mode 100644 index 00000000000..02cec85ae07 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert2.spec @@ -0,0 +1,54 @@ +# Test interaction between concurrent transactions performing +# create and insert in REPEATABLE READ isolation level +# +# Note: +# In this isolation level, it is possible that create_immv could +# create an inconsistent view not including effects of a concurrent +# transaction. So, an warning message is raised to suggest using it +# in READ COMMITTED or executing refresh_immv to make sure to +# make the view contents consistent. + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-create-insert3.spec b/src/test/isolation/specs/ivm-create-insert3.spec new file mode 100644 index 00000000000..19ce03185a4 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert3.spec @@ -0,0 +1,54 @@ +# Test interaction between concurrent transactions performing +# create and insert in SERIALIZABLE isolation level +# +# Note: +# In this isolation level, it is possible that create_immv could +# create an inconsistent view not including effects of a concurrent +# transaction. So, an warning message is raised to suggest using it +# in READ COMMITTED or executing refresh_immv to make sure to +# make the view contents consistent. + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert.spec b/src/test/isolation/specs/ivm-insert-insert.spec new file mode 100644 index 00000000000..b8f794ca191 --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert2.spec b/src/test/isolation/specs/ivm-insert-insert2.spec new file mode 100644 index 00000000000..ed086d1ba1e --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert2.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in REPEATABLE READ isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert3.spec b/src/test/isolation/specs/ivm-insert-insert3.spec new file mode 100644 index 00000000000..b18bd121033 --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert3.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in SERIALIZABLE isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert.spec b/src/test/isolation/specs/ivm-refresh-insert.spec new file mode 100644 index 00000000000..d7181251962 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert2.spec b/src/test/isolation/specs/ivm-refresh-insert2.spec new file mode 100644 index 00000000000..f2d1d5013f2 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert2.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in REPEATABLE READ isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert3.spec b/src/test/isolation/specs/ivm-refresh-insert3.spec new file mode 100644 index 00000000000..0ec2b1d1de0 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert3.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in SERIALIZABLE isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/regress/expected/incremental_matview.out b/src/test/regress/expected/incremental_matview.out new file mode 100644 index 00000000000..c7fd19fdca3 --- /dev/null +++ b/src/test/regress/expected/incremental_matview.out @@ -0,0 +1,667 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ERROR: materialized view "mv_ivm_1" has not been populated +HINT: Use the REFRESH MATERIALIZED VIEW command. +REFRESH MATERIALIZED VIEW mv_ivm_1; +NOTICE: could not create an index on materialized view "mv_ivm_1" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 17 +(1 row) + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 1 +(1 row) + +ROLLBACK; +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- DISTINCT not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT * FROM mv_base_a; +ERROR: DISTINCT is not supported on incrementally maintainable materialized view +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +NOTICE: could not create an index on materialized view "mv_ivm_func" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +NOTICE: could not create an index on materialized view "mv_ivm_no_tbl" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- result of materialized view have duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_duplicate" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 20 + 30 + 40 + 50 +(6 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +ROLLBACK; +-- aggregate not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +ERROR: aggregate function is not supported on incrementally maintainable materialized view +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +NOTICE: could not create an index on materialized view "mv_self" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +----+---- + 10 | 10 + 20 | 20 + 30 | 30 +(3 rows) + +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 30 | 30 + 40 | 40 + 200 | 200 +(3 rows) + +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 130 | 130 + 300 | 300 +(4 rows) + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 70 | 70 + 70 | 77 + 77 | 70 + 77 | 77 + 130 | 130 + 300 | 300 +(8 rows) + +ROLLBACK; +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY v1; + v1 | v2 +----+----- + 10 | 100 + 20 | 200 + 30 | 300 +(3 rows) + +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv ORDER BY v1; + v1 | v2 +------+----- + 10 | 100 + 11 | 100 + 1020 | 200 + 1020 | 222 +(4 rows) + +ROLLBACK; +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +NOTICE: created index "mv_ri_index" on materialized view "mv_ri" +SELECT * FROM mv_ri ORDER BY i1; + i1 | i2 +----+---- + 1 | 1 + 2 | 2 + 3 | 3 +(3 rows) + +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; + i1 | i2 +----+---- + 3 | 3 + 10 | 10 +(2 rows) + +ROLLBACK; +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | +(2 rows) + +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | 20 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i +--- +(0 rows) + +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; + i +--- + 1 + +(2 rows) + +ROLLBACK; +-- IMMV containing user defined type +BEGIN; +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: return type mytype is only a shell +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: argument type mytype is only a shell +LINE 1: CREATE FUNCTION mytype_out(mytype) + ^ +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +NOTICE: could not create an index on materialized view "mv_mytype" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + x +--- + 1 +(1 row) + +ROLLBACK; +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +ERROR: OUTER JOIN is not supported on incrementally maintainable materialized view +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +ERROR: CTE is not supported on incrementally maintainable materialized view +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +ERROR: ORDER BY clause is not supported on incrementally maintainable materialized view +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; +ERROR: HAVING clause is not supported on incrementally maintainable materialized view +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; +ERROR: mutable function is not supported on incrementally maintainable materialized view +HINT: functions must be marked IMMUTABLE +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; +ERROR: LIMIT/OFFSET clause is not supported on incrementally maintainable materialized view +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; +ERROR: DISTINCT is not supported on incrementally maintainable materialized view +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); +ERROR: TABLESAMPLE clause is not supported on incrementally maintainable materialized view +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; +ERROR: window functions are not supported on incrementally maintainable materialized view +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ERROR: inheritance parent is not supported on incrementally maintainable materialized view +ROLLBACK; +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; +ERROR: UNION/INTERSECT/EXCEPT statements are not supported on incrementally maintainable materialized view +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; +ERROR: empty target list is not supported on incrementally maintainable materialized view +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; +ERROR: FOR UPDATE/SHARE clause is not supported on incrementally maintainable materialized view +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; +ERROR: column name __ivm_count__ is not supported on incrementally maintainable materialized view +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; +ERROR: aggregate function is not supported on incrementally maintainable materialized view +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); +ERROR: VALUES is not supported on incrementally maintainable materialized view +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +NOTICE: role "regress_ivm_admin" does not exist, skipping +DROP USER IF EXISTS regress_ivm_user; +NOTICE: role "regress_ivm_user" does not exist, skipping +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +NOTICE: could not create an index on materialized view "ivm_rls" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user +(1 row) + +RESET SESSION AUTHORIZATION; +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user + 3 | baz | regress_ivm_user +(2 rows) + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +-- +(1 row) + +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+-------+------------------ + 2 | bar | regress_ivm_user + 3 | baz | regress_ivm_user + 6 | corge | regress_ivm_user +(3 rows) + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +NOTICE: could not create an index on materialized view "ivm_rls2" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +RESET SESSION AUTHORIZATION; +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +-- +(1 row) + +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + id | data | owner | num +----+-------+------------------+--------- + 2 | bar | regress_ivm_user | two + 3 | baz_2 | regress_ivm_user | three_2 + 6 | corge | regress_ivm_user | six +(3 rows) + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +NOTICE: could not create an index on materialized view "mv_update_same" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + i +--- + 2 +(1 row) + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +NOTICE: created index "mv_self_ref_index" on materialized view "mv_self_ref" +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; + a | b +----+---- + 11 | + 12 | 11 + 13 | 12 +(3 rows) + +ROLLBACK; +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; +NOTICE: created index "mv_idx3_index" on materialized view "mv_idx3" +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +NOTICE: could not create an index on materialized view "mv_idx4" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; +NOTICE: could not create an index on materialized view "mv_idx5" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); +NOTICE: could not create an index on materialized view "mv_idx6" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ERROR: data type json has no default operator class for access method "btree" +ROLLBACK; +-- cleanup +DROP TABLE rls_tbl CASCADE; +NOTICE: drop cascades to 2 other objects +DETAIL: drop cascades to materialized view ivm_rls +drop cascades to materialized view ivm_rls2 +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; +DROP TABLE mv_base_b CASCADE; +NOTICE: drop cascades to 3 other objects +DETAIL: drop cascades to materialized view mv_ivm_1 +drop cascades to view b_view +drop cascades to materialized view b_mview +DROP TABLE mv_base_a CASCADE; diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index 8fa0a6c47fb..7caca5f64fd 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -77,6 +77,7 @@ test: brin_bloom brin_multi # Another group of parallel tests # ---------- test: create_table_like alter_generic alter_operator misc async dbsize merge misc_functions nls sysviews tsrf tid tidscan tidrangescan collate.utf8 collate.icu.utf8 incremental_sort create_role without_overlaps generated_virtual +test: incremental_matview # collate.linux.utf8 and collate.icu.utf8 tests cannot be run in parallel with each other # psql depends on create_am diff --git a/src/test/regress/sql/incremental_matview.sql b/src/test/regress/sql/incremental_matview.sql new file mode 100644 index 00000000000..7313ad82f3e --- /dev/null +++ b/src/test/regress/sql/incremental_matview.sql @@ -0,0 +1,407 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); + +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +REFRESH MATERIALIZED VIEW mv_ivm_1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; + +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; +ROLLBACK; + +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- DISTINCT not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT * FROM mv_base_a; + +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; + + +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +ROLLBACK; + +-- result of materialized view have duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +ROLLBACK; + +-- aggregate not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; + +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +SELECT * FROM mv_self ORDER BY v1; +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; +SELECT * FROM mv_self ORDER BY v1; + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + +ROLLBACK; + +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +SELECT * FROM mv ORDER BY v1; +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; +SELECT * FROM mv ORDER BY v1; +ROLLBACK; + +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +SELECT * FROM mv_ri ORDER BY i1; +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; +ROLLBACK; + +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +-- IMMV containing user defined type +BEGIN; + +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); + +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; + +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); + +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); + +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + +ROLLBACK; + +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; + +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; + +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; + +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; + +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; + +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); + +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; + +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ROLLBACK; + +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; + +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; + +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; + +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; + +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; + +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); + +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +DROP USER IF EXISTS regress_ivm_user; +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; + +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); + +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; + +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; + +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; +RESET SESSION AUTHORIZATION; + +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +RESET SESSION AUTHORIZATION; + +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; +ROLLBACK; + +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); + +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; + +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; + +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); + +ROLLBACK; + +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ROLLBACK; + +-- cleanup + +DROP TABLE rls_tbl CASCADE; +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; + +DROP TABLE mv_base_b CASCADE; +DROP TABLE mv_base_a CASCADE; -- 2.43.0 --Multipart=_Fri__3_Jul_2026_19_11_16_+0900_CskxSIu_iGcDMEyM Content-Type: text/x-diff; name="v39-0006-Add-Incremental-View-Maintenance-support.patch" Content-Disposition: attachment; filename="v39-0006-Add-Incremental-View-Maintenance-support.patch" Content-Transfer-Encoding: 7bit ^ permalink raw reply [nested|flat] 78+ messages in thread
* [PATCH v39 7/8] Add regression tests for Incremental View Maintenance @ 2026-05-29 09:31 Yugo Nagata <[email protected]> 0 siblings, 0 replies; 78+ messages in thread From: Yugo Nagata @ 2026-05-29 09:31 UTC (permalink / raw) --- .../isolation/expected/ivm-create-insert.out | 285 ++++++++ .../isolation/expected/ivm-create-insert2.out | 305 ++++++++ .../isolation/expected/ivm-create-insert3.out | 305 ++++++++ .../isolation/expected/ivm-insert-insert.out | 497 +++++++++++++ .../isolation/expected/ivm-insert-insert2.out | 373 ++++++++++ .../isolation/expected/ivm-insert-insert3.out | 373 ++++++++++ .../isolation/expected/ivm-refresh-insert.out | 213 ++++++ .../expected/ivm-refresh-insert2.out | 191 +++++ .../expected/ivm-refresh-insert3.out | 191 +++++ src/test/isolation/isolation_schedule | 9 + .../isolation/specs/ivm-create-insert.spec | 47 ++ .../isolation/specs/ivm-create-insert2.spec | 54 ++ .../isolation/specs/ivm-create-insert3.spec | 54 ++ .../isolation/specs/ivm-insert-insert.spec | 62 ++ .../isolation/specs/ivm-insert-insert2.spec | 62 ++ .../isolation/specs/ivm-insert-insert3.spec | 62 ++ .../isolation/specs/ivm-refresh-insert.spec | 46 ++ .../isolation/specs/ivm-refresh-insert2.spec | 46 ++ .../isolation/specs/ivm-refresh-insert3.spec | 46 ++ .../regress/expected/incremental_matview.out | 667 ++++++++++++++++++ src/test/regress/parallel_schedule | 1 + src/test/regress/sql/incremental_matview.sql | 407 +++++++++++ 22 files changed, 4296 insertions(+) create mode 100644 src/test/isolation/expected/ivm-create-insert.out create mode 100644 src/test/isolation/expected/ivm-create-insert2.out create mode 100644 src/test/isolation/expected/ivm-create-insert3.out create mode 100644 src/test/isolation/expected/ivm-insert-insert.out create mode 100644 src/test/isolation/expected/ivm-insert-insert2.out create mode 100644 src/test/isolation/expected/ivm-insert-insert3.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert2.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert3.out create mode 100644 src/test/isolation/specs/ivm-create-insert.spec create mode 100644 src/test/isolation/specs/ivm-create-insert2.spec create mode 100644 src/test/isolation/specs/ivm-create-insert3.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert2.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert3.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert2.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert3.spec create mode 100644 src/test/regress/expected/incremental_matview.out create mode 100644 src/test/regress/sql/incremental_matview.sql diff --git a/src/test/isolation/expected/ivm-create-insert.out b/src/test/isolation/expected/ivm-create-insert.out new file mode 100644 index 00000000000..5da00043aba --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert.out @@ -0,0 +1,285 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-create-insert2.out b/src/test/isolation/expected/ivm-create-insert2.out new file mode 100644 index 00000000000..907d892c6d4 --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert2.out @@ -0,0 +1,305 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + diff --git a/src/test/isolation/expected/ivm-create-insert3.out b/src/test/isolation/expected/ivm-create-insert3.out new file mode 100644 index 00000000000..907d892c6d4 --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert3.out @@ -0,0 +1,305 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert.out b/src/test/isolation/expected/ivm-insert-insert.out new file mode 100644 index 00000000000..5ca4cfea677 --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert.out @@ -0,0 +1,497 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; <waiting ...> +step c1: COMMIT; +step update2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; <waiting ...> +step c1: COMMIT; +step update2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; <waiting ...> +step c2: COMMIT; +step update1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; <waiting ...> +step c2: COMMIT; +step update1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); <waiting ...> +step c1: COMMIT; +step insert2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); <waiting ...> +step c1: COMMIT; +step insert2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); <waiting ...> +step c2: COMMIT; +step insert1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); <waiting ...> +step c2: COMMIT; +step insert1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert2.out b/src/test/isolation/expected/ivm-insert-insert2.out new file mode 100644 index 00000000000..e1c66d4de5e --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert2.out @@ -0,0 +1,373 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert3.out b/src/test/isolation/expected/ivm-insert-insert3.out new file mode 100644 index 00000000000..e1c66d4de5e --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert3.out @@ -0,0 +1,373 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert.out b/src/test/isolation/expected/ivm-refresh-insert.out new file mode 100644 index 00000000000..a925938bf1c --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert.out @@ -0,0 +1,213 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert2.out b/src/test/isolation/expected/ivm-refresh-insert2.out new file mode 100644 index 00000000000..dc1b16ae34e --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert2.out @@ -0,0 +1,191 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert3.out b/src/test/isolation/expected/ivm-refresh-insert3.out new file mode 100644 index 00000000000..dc1b16ae34e --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert3.out @@ -0,0 +1,191 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/isolation_schedule b/src/test/isolation/isolation_schedule index b8ebe92553c..6b7e873b370 100644 --- a/src/test/isolation/isolation_schedule +++ b/src/test/isolation/isolation_schedule @@ -128,3 +128,12 @@ test: matview-write-skew test: lock-nowait test: for-portion-of test: ddl-dependency-locking +test: ivm-create-insert +test: ivm-create-insert2 +test: ivm-create-insert3 +test: ivm-insert-insert +test: ivm-insert-insert2 +test: ivm-insert-insert3 +test: ivm-refresh-insert +test: ivm-refresh-insert2 +test: ivm-refresh-insert3 diff --git a/src/test/isolation/specs/ivm-create-insert.spec b/src/test/isolation/specs/ivm-create-insert.spec new file mode 100644 index 00000000000..ccd6fd080a9 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert.spec @@ -0,0 +1,47 @@ +# Test interaction between concurrent transactions performing +# create and insert in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-create-insert2.spec b/src/test/isolation/specs/ivm-create-insert2.spec new file mode 100644 index 00000000000..02cec85ae07 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert2.spec @@ -0,0 +1,54 @@ +# Test interaction between concurrent transactions performing +# create and insert in REPEATABLE READ isolation level +# +# Note: +# In this isolation level, it is possible that create_immv could +# create an inconsistent view not including effects of a concurrent +# transaction. So, an warning message is raised to suggest using it +# in READ COMMITTED or executing refresh_immv to make sure to +# make the view contents consistent. + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-create-insert3.spec b/src/test/isolation/specs/ivm-create-insert3.spec new file mode 100644 index 00000000000..19ce03185a4 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert3.spec @@ -0,0 +1,54 @@ +# Test interaction between concurrent transactions performing +# create and insert in SERIALIZABLE isolation level +# +# Note: +# In this isolation level, it is possible that create_immv could +# create an inconsistent view not including effects of a concurrent +# transaction. So, an warning message is raised to suggest using it +# in READ COMMITTED or executing refresh_immv to make sure to +# make the view contents consistent. + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert.spec b/src/test/isolation/specs/ivm-insert-insert.spec new file mode 100644 index 00000000000..b8f794ca191 --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert2.spec b/src/test/isolation/specs/ivm-insert-insert2.spec new file mode 100644 index 00000000000..ed086d1ba1e --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert2.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in REPEATABLE READ isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert3.spec b/src/test/isolation/specs/ivm-insert-insert3.spec new file mode 100644 index 00000000000..b18bd121033 --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert3.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in SERIALIZABLE isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert.spec b/src/test/isolation/specs/ivm-refresh-insert.spec new file mode 100644 index 00000000000..d7181251962 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert2.spec b/src/test/isolation/specs/ivm-refresh-insert2.spec new file mode 100644 index 00000000000..f2d1d5013f2 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert2.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in REPEATABLE READ isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert3.spec b/src/test/isolation/specs/ivm-refresh-insert3.spec new file mode 100644 index 00000000000..0ec2b1d1de0 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert3.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in SERIALIZABLE isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/regress/expected/incremental_matview.out b/src/test/regress/expected/incremental_matview.out new file mode 100644 index 00000000000..c7fd19fdca3 --- /dev/null +++ b/src/test/regress/expected/incremental_matview.out @@ -0,0 +1,667 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ERROR: materialized view "mv_ivm_1" has not been populated +HINT: Use the REFRESH MATERIALIZED VIEW command. +REFRESH MATERIALIZED VIEW mv_ivm_1; +NOTICE: could not create an index on materialized view "mv_ivm_1" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 17 +(1 row) + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 1 +(1 row) + +ROLLBACK; +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- DISTINCT not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT * FROM mv_base_a; +ERROR: DISTINCT is not supported on incrementally maintainable materialized view +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +NOTICE: could not create an index on materialized view "mv_ivm_func" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +NOTICE: could not create an index on materialized view "mv_ivm_no_tbl" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- result of materialized view have duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_duplicate" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 20 + 30 + 40 + 50 +(6 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +ROLLBACK; +-- aggregate not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +ERROR: aggregate function is not supported on incrementally maintainable materialized view +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +NOTICE: could not create an index on materialized view "mv_self" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +----+---- + 10 | 10 + 20 | 20 + 30 | 30 +(3 rows) + +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 30 | 30 + 40 | 40 + 200 | 200 +(3 rows) + +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 130 | 130 + 300 | 300 +(4 rows) + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 70 | 70 + 70 | 77 + 77 | 70 + 77 | 77 + 130 | 130 + 300 | 300 +(8 rows) + +ROLLBACK; +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY v1; + v1 | v2 +----+----- + 10 | 100 + 20 | 200 + 30 | 300 +(3 rows) + +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv ORDER BY v1; + v1 | v2 +------+----- + 10 | 100 + 11 | 100 + 1020 | 200 + 1020 | 222 +(4 rows) + +ROLLBACK; +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +NOTICE: created index "mv_ri_index" on materialized view "mv_ri" +SELECT * FROM mv_ri ORDER BY i1; + i1 | i2 +----+---- + 1 | 1 + 2 | 2 + 3 | 3 +(3 rows) + +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; + i1 | i2 +----+---- + 3 | 3 + 10 | 10 +(2 rows) + +ROLLBACK; +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | +(2 rows) + +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | 20 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i +--- +(0 rows) + +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; + i +--- + 1 + +(2 rows) + +ROLLBACK; +-- IMMV containing user defined type +BEGIN; +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: return type mytype is only a shell +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: argument type mytype is only a shell +LINE 1: CREATE FUNCTION mytype_out(mytype) + ^ +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +NOTICE: could not create an index on materialized view "mv_mytype" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + x +--- + 1 +(1 row) + +ROLLBACK; +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +ERROR: OUTER JOIN is not supported on incrementally maintainable materialized view +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +ERROR: CTE is not supported on incrementally maintainable materialized view +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +ERROR: ORDER BY clause is not supported on incrementally maintainable materialized view +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; +ERROR: HAVING clause is not supported on incrementally maintainable materialized view +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; +ERROR: mutable function is not supported on incrementally maintainable materialized view +HINT: functions must be marked IMMUTABLE +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; +ERROR: LIMIT/OFFSET clause is not supported on incrementally maintainable materialized view +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; +ERROR: DISTINCT is not supported on incrementally maintainable materialized view +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); +ERROR: TABLESAMPLE clause is not supported on incrementally maintainable materialized view +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; +ERROR: window functions are not supported on incrementally maintainable materialized view +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ERROR: inheritance parent is not supported on incrementally maintainable materialized view +ROLLBACK; +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; +ERROR: UNION/INTERSECT/EXCEPT statements are not supported on incrementally maintainable materialized view +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; +ERROR: empty target list is not supported on incrementally maintainable materialized view +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; +ERROR: FOR UPDATE/SHARE clause is not supported on incrementally maintainable materialized view +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; +ERROR: column name __ivm_count__ is not supported on incrementally maintainable materialized view +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; +ERROR: aggregate function is not supported on incrementally maintainable materialized view +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); +ERROR: VALUES is not supported on incrementally maintainable materialized view +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +NOTICE: role "regress_ivm_admin" does not exist, skipping +DROP USER IF EXISTS regress_ivm_user; +NOTICE: role "regress_ivm_user" does not exist, skipping +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +NOTICE: could not create an index on materialized view "ivm_rls" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user +(1 row) + +RESET SESSION AUTHORIZATION; +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user + 3 | baz | regress_ivm_user +(2 rows) + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +-- +(1 row) + +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+-------+------------------ + 2 | bar | regress_ivm_user + 3 | baz | regress_ivm_user + 6 | corge | regress_ivm_user +(3 rows) + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +NOTICE: could not create an index on materialized view "ivm_rls2" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +RESET SESSION AUTHORIZATION; +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +-- +(1 row) + +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + id | data | owner | num +----+-------+------------------+--------- + 2 | bar | regress_ivm_user | two + 3 | baz_2 | regress_ivm_user | three_2 + 6 | corge | regress_ivm_user | six +(3 rows) + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +NOTICE: could not create an index on materialized view "mv_update_same" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + i +--- + 2 +(1 row) + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +NOTICE: created index "mv_self_ref_index" on materialized view "mv_self_ref" +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; + a | b +----+---- + 11 | + 12 | 11 + 13 | 12 +(3 rows) + +ROLLBACK; +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; +NOTICE: created index "mv_idx3_index" on materialized view "mv_idx3" +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +NOTICE: could not create an index on materialized view "mv_idx4" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; +NOTICE: could not create an index on materialized view "mv_idx5" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); +NOTICE: could not create an index on materialized view "mv_idx6" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ERROR: data type json has no default operator class for access method "btree" +ROLLBACK; +-- cleanup +DROP TABLE rls_tbl CASCADE; +NOTICE: drop cascades to 2 other objects +DETAIL: drop cascades to materialized view ivm_rls +drop cascades to materialized view ivm_rls2 +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; +DROP TABLE mv_base_b CASCADE; +NOTICE: drop cascades to 3 other objects +DETAIL: drop cascades to materialized view mv_ivm_1 +drop cascades to view b_view +drop cascades to materialized view b_mview +DROP TABLE mv_base_a CASCADE; diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index 8fa0a6c47fb..7caca5f64fd 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -77,6 +77,7 @@ test: brin_bloom brin_multi # Another group of parallel tests # ---------- test: create_table_like alter_generic alter_operator misc async dbsize merge misc_functions nls sysviews tsrf tid tidscan tidrangescan collate.utf8 collate.icu.utf8 incremental_sort create_role without_overlaps generated_virtual +test: incremental_matview # collate.linux.utf8 and collate.icu.utf8 tests cannot be run in parallel with each other # psql depends on create_am diff --git a/src/test/regress/sql/incremental_matview.sql b/src/test/regress/sql/incremental_matview.sql new file mode 100644 index 00000000000..7313ad82f3e --- /dev/null +++ b/src/test/regress/sql/incremental_matview.sql @@ -0,0 +1,407 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); + +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +REFRESH MATERIALIZED VIEW mv_ivm_1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; + +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; +ROLLBACK; + +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- DISTINCT not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT * FROM mv_base_a; + +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; + + +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +ROLLBACK; + +-- result of materialized view have duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +ROLLBACK; + +-- aggregate not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; + +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +SELECT * FROM mv_self ORDER BY v1; +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; +SELECT * FROM mv_self ORDER BY v1; + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + +ROLLBACK; + +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +SELECT * FROM mv ORDER BY v1; +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; +SELECT * FROM mv ORDER BY v1; +ROLLBACK; + +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +SELECT * FROM mv_ri ORDER BY i1; +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; +ROLLBACK; + +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +-- IMMV containing user defined type +BEGIN; + +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); + +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; + +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); + +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); + +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + +ROLLBACK; + +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; + +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; + +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; + +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; + +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; + +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); + +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; + +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ROLLBACK; + +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; + +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; + +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; + +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; + +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; + +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); + +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +DROP USER IF EXISTS regress_ivm_user; +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; + +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); + +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; + +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; + +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; +RESET SESSION AUTHORIZATION; + +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +RESET SESSION AUTHORIZATION; + +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; +ROLLBACK; + +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); + +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; + +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; + +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); + +ROLLBACK; + +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ROLLBACK; + +-- cleanup + +DROP TABLE rls_tbl CASCADE; +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; + +DROP TABLE mv_base_b CASCADE; +DROP TABLE mv_base_a CASCADE; -- 2.43.0 --Multipart=_Fri__3_Jul_2026_19_11_16_+0900_CskxSIu_iGcDMEyM Content-Type: text/x-diff; name="v39-0006-Add-Incremental-View-Maintenance-support.patch" Content-Disposition: attachment; filename="v39-0006-Add-Incremental-View-Maintenance-support.patch" Content-Transfer-Encoding: 7bit ^ permalink raw reply [nested|flat] 78+ messages in thread
* [PATCH v38 10/11] Add regression tests for Incremental View Maintenance @ 2026-05-29 09:31 Yugo Nagata <[email protected]> 0 siblings, 0 replies; 78+ messages in thread From: Yugo Nagata @ 2026-05-29 09:31 UTC (permalink / raw) --- .../isolation/expected/ivm-create-insert.out | 285 +++++ .../isolation/expected/ivm-create-insert2.out | 305 +++++ .../isolation/expected/ivm-create-insert3.out | 305 +++++ .../isolation/expected/ivm-insert-insert.out | 497 ++++++++ .../isolation/expected/ivm-insert-insert2.out | 373 ++++++ .../isolation/expected/ivm-insert-insert3.out | 373 ++++++ .../isolation/expected/ivm-refresh-insert.out | 213 ++++ .../expected/ivm-refresh-insert2.out | 191 +++ .../expected/ivm-refresh-insert3.out | 191 +++ src/test/isolation/isolation_schedule | 9 + .../isolation/specs/ivm-create-insert.spec | 47 + .../isolation/specs/ivm-create-insert2.spec | 54 + .../isolation/specs/ivm-create-insert3.spec | 54 + .../isolation/specs/ivm-insert-insert.spec | 62 + .../isolation/specs/ivm-insert-insert2.spec | 62 + .../isolation/specs/ivm-insert-insert3.spec | 62 + .../isolation/specs/ivm-refresh-insert.spec | 46 + .../isolation/specs/ivm-refresh-insert2.spec | 46 + .../isolation/specs/ivm-refresh-insert3.spec | 46 + .../regress/expected/incremental_matview.out | 1100 +++++++++++++++++ src/test/regress/parallel_schedule | 1 + src/test/regress/sql/incremental_matview.sql | 580 +++++++++ 22 files changed, 4902 insertions(+) create mode 100644 src/test/isolation/expected/ivm-create-insert.out create mode 100644 src/test/isolation/expected/ivm-create-insert2.out create mode 100644 src/test/isolation/expected/ivm-create-insert3.out create mode 100644 src/test/isolation/expected/ivm-insert-insert.out create mode 100644 src/test/isolation/expected/ivm-insert-insert2.out create mode 100644 src/test/isolation/expected/ivm-insert-insert3.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert2.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert3.out create mode 100644 src/test/isolation/specs/ivm-create-insert.spec create mode 100644 src/test/isolation/specs/ivm-create-insert2.spec create mode 100644 src/test/isolation/specs/ivm-create-insert3.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert2.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert3.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert2.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert3.spec create mode 100644 src/test/regress/expected/incremental_matview.out create mode 100644 src/test/regress/sql/incremental_matview.sql diff --git a/src/test/isolation/expected/ivm-create-insert.out b/src/test/isolation/expected/ivm-create-insert.out new file mode 100644 index 00000000000..5da00043aba --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert.out @@ -0,0 +1,285 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-create-insert2.out b/src/test/isolation/expected/ivm-create-insert2.out new file mode 100644 index 00000000000..907d892c6d4 --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert2.out @@ -0,0 +1,305 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + diff --git a/src/test/isolation/expected/ivm-create-insert3.out b/src/test/isolation/expected/ivm-create-insert3.out new file mode 100644 index 00000000000..907d892c6d4 --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert3.out @@ -0,0 +1,305 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert.out b/src/test/isolation/expected/ivm-insert-insert.out new file mode 100644 index 00000000000..5ca4cfea677 --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert.out @@ -0,0 +1,497 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; <waiting ...> +step c1: COMMIT; +step update2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; <waiting ...> +step c1: COMMIT; +step update2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; <waiting ...> +step c2: COMMIT; +step update1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; <waiting ...> +step c2: COMMIT; +step update1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); <waiting ...> +step c1: COMMIT; +step insert2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); <waiting ...> +step c1: COMMIT; +step insert2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); <waiting ...> +step c2: COMMIT; +step insert1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); <waiting ...> +step c2: COMMIT; +step insert1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert2.out b/src/test/isolation/expected/ivm-insert-insert2.out new file mode 100644 index 00000000000..e1c66d4de5e --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert2.out @@ -0,0 +1,373 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert3.out b/src/test/isolation/expected/ivm-insert-insert3.out new file mode 100644 index 00000000000..e1c66d4de5e --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert3.out @@ -0,0 +1,373 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert.out b/src/test/isolation/expected/ivm-refresh-insert.out new file mode 100644 index 00000000000..a925938bf1c --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert.out @@ -0,0 +1,213 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert2.out b/src/test/isolation/expected/ivm-refresh-insert2.out new file mode 100644 index 00000000000..dc1b16ae34e --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert2.out @@ -0,0 +1,191 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert3.out b/src/test/isolation/expected/ivm-refresh-insert3.out new file mode 100644 index 00000000000..dc1b16ae34e --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert3.out @@ -0,0 +1,191 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/isolation_schedule b/src/test/isolation/isolation_schedule index b8ebe92553c..6b7e873b370 100644 --- a/src/test/isolation/isolation_schedule +++ b/src/test/isolation/isolation_schedule @@ -128,3 +128,12 @@ test: matview-write-skew test: lock-nowait test: for-portion-of test: ddl-dependency-locking +test: ivm-create-insert +test: ivm-create-insert2 +test: ivm-create-insert3 +test: ivm-insert-insert +test: ivm-insert-insert2 +test: ivm-insert-insert3 +test: ivm-refresh-insert +test: ivm-refresh-insert2 +test: ivm-refresh-insert3 diff --git a/src/test/isolation/specs/ivm-create-insert.spec b/src/test/isolation/specs/ivm-create-insert.spec new file mode 100644 index 00000000000..ccd6fd080a9 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert.spec @@ -0,0 +1,47 @@ +# Test interaction between concurrent transactions performing +# create and insert in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-create-insert2.spec b/src/test/isolation/specs/ivm-create-insert2.spec new file mode 100644 index 00000000000..02cec85ae07 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert2.spec @@ -0,0 +1,54 @@ +# Test interaction between concurrent transactions performing +# create and insert in REPEATABLE READ isolation level +# +# Note: +# In this isolation level, it is possible that create_immv could +# create an inconsistent view not including effects of a concurrent +# transaction. So, an warning message is raised to suggest using it +# in READ COMMITTED or executing refresh_immv to make sure to +# make the view contents consistent. + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-create-insert3.spec b/src/test/isolation/specs/ivm-create-insert3.spec new file mode 100644 index 00000000000..19ce03185a4 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert3.spec @@ -0,0 +1,54 @@ +# Test interaction between concurrent transactions performing +# create and insert in SERIALIZABLE isolation level +# +# Note: +# In this isolation level, it is possible that create_immv could +# create an inconsistent view not including effects of a concurrent +# transaction. So, an warning message is raised to suggest using it +# in READ COMMITTED or executing refresh_immv to make sure to +# make the view contents consistent. + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert.spec b/src/test/isolation/specs/ivm-insert-insert.spec new file mode 100644 index 00000000000..b8f794ca191 --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert2.spec b/src/test/isolation/specs/ivm-insert-insert2.spec new file mode 100644 index 00000000000..ed086d1ba1e --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert2.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in REPEATABLE READ isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert3.spec b/src/test/isolation/specs/ivm-insert-insert3.spec new file mode 100644 index 00000000000..b18bd121033 --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert3.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in SERIALIZABLE isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert.spec b/src/test/isolation/specs/ivm-refresh-insert.spec new file mode 100644 index 00000000000..d7181251962 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert2.spec b/src/test/isolation/specs/ivm-refresh-insert2.spec new file mode 100644 index 00000000000..f2d1d5013f2 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert2.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in REPEATABLE READ isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert3.spec b/src/test/isolation/specs/ivm-refresh-insert3.spec new file mode 100644 index 00000000000..0ec2b1d1de0 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert3.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in SERIALIZABLE isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/regress/expected/incremental_matview.out b/src/test/regress/expected/incremental_matview.out new file mode 100644 index 00000000000..f215aa88e48 --- /dev/null +++ b/src/test/regress/expected/incremental_matview.out @@ -0,0 +1,1100 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ERROR: materialized view "mv_ivm_1" has not been populated +HINT: Use the REFRESH MATERIALIZED VIEW command. +REFRESH MATERIALIZED VIEW mv_ivm_1; +NOTICE: could not create an index on materialized view "mv_ivm_1" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 17 +(1 row) + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 1 +(1 row) + +ROLLBACK; +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_rename_index" on materialized view "mv_ivm_rename" +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +ERROR: IVM column can not be renamed +DROP MATERIALIZED VIEW mv_ivm_rename; +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_unique_index" on materialized view "mv_ivm_unique" +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +ERROR: unique index creation on IVM columns is not supported +DROP MATERIALIZED VIEW mv_ivm_unique; +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +NOTICE: could not create an index on materialized view "mv_ivm_func" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +NOTICE: could not create an index on materialized view "mv_ivm_no_tbl" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_duplicate" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +NOTICE: created index "mv_ivm_distinct_index" on materialized view "mv_ivm_distinct" +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 20 + 30 + 40 + 50 +(6 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +ROLLBACK; +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 120 | 2 | 60.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+---------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 220 | 2 | 110.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 20 | 1 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 120 | 2 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; + sum | count +-----+------- +(0 rows) + +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; + i | sum | count +---+-----+------- +(0 rows) + +ROLLBACK; +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 150 | 5 | 30.0000000000000000 +(1 row) + +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 210 | 6 | 35.0000000000000000 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +NOTICE: created index "mv_ivm_avg_bug_index" on materialized view "mv_ivm_avg_bug" +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 3 | 3.3333333333333333 + 2 | 80 | 3 | 26.6666666666666667 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_min_max_index" on materialized view "mv_ivm_min_max" +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 10 + 2 | 20 | 20 + 3 | 30 | 30 + 4 | 40 | 40 + 5 | 50 | 50 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 12 + 2 | 20 | 22 + 3 | 30 | 32 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 11 | 12 + 2 | 20 | 22 + 3 | 30 | 31 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min_max" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 50 +(1 row) + +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 0 | 70 +(1 row) + +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 60 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + | +(1 row) + +ROLLBACK; +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min; + min +----- + 10 +(1 row) + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + min +----- + 20 +(1 row) + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; + min +----- + 30 +(1 row) + +ROLLBACK; +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | sum +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | b +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ERROR: too many column names were specified +ROLLBACK; +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +NOTICE: could not create an index on materialized view "mv_self" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +----+---- + 10 | 10 + 20 | 20 + 30 | 30 +(3 rows) + +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 30 | 30 + 40 | 40 + 200 | 200 +(3 rows) + +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 130 | 130 + 300 | 300 +(4 rows) + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 70 | 70 + 70 | 77 + 77 | 70 + 77 | 77 + 130 | 130 + 300 | 300 +(8 rows) + +ROLLBACK; +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY v1; + v1 | v2 +----+----- + 10 | 100 + 20 | 200 + 30 | 300 +(3 rows) + +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv ORDER BY v1; + v1 | v2 +------+----- + 10 | 100 + 11 | 100 + 1020 | 200 + 1020 | 222 +(4 rows) + +ROLLBACK; +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +NOTICE: created index "mv_ri_index" on materialized view "mv_ri" +SELECT * FROM mv_ri ORDER BY i1; + i1 | i2 +----+---- + 1 | 1 + 2 | 2 + 3 | 3 +(3 rows) + +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; + i1 | i2 +----+---- + 3 | 3 + 10 | 10 +(2 rows) + +ROLLBACK; +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | +(2 rows) + +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | 20 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i +--- +(0 rows) + +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; + i +--- + 1 + +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 30 + | 3 +(2 rows) + +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 300 + | 30 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 1 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 4 +(1 row) + +ROLLBACK; +-- IMMV containing user defined type +BEGIN; +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: return type mytype is only a shell +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: argument type mytype is only a shell +LINE 1: CREATE FUNCTION mytype_out(mytype) + ^ +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +NOTICE: could not create an index on materialized view "mv_mytype" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + x +--- + 1 +(1 row) + +ROLLBACK; +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +ERROR: OUTER JOIN is not supported on incrementally maintainable materialized view +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +ERROR: CTE is not supported on incrementally maintainable materialized view +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +ERROR: ORDER BY clause is not supported on incrementally maintainable materialized view +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; +ERROR: HAVING clause is not supported on incrementally maintainable materialized view +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; +ERROR: mutable function is not supported on incrementally maintainable materialized view +HINT: functions must be marked IMMUTABLE +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; +ERROR: LIMIT/OFFSET clause is not supported on incrementally maintainable materialized view +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; +ERROR: DISTINCT ON is not supported on incrementally maintainable materialized view +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); +ERROR: TABLESAMPLE clause is not supported on incrementally maintainable materialized view +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; +ERROR: window functions are not supported on incrementally maintainable materialized view +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +ERROR: aggregate function with FILTER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +ERROR: aggregate function with DISTINCT arguments is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +ERROR: aggregate function with ORDER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); +ERROR: GROUPING SETS, ROLLUP, or CUBE clauses is not supported on incrementally maintainable materialized view +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ERROR: inheritance parent is not supported on incrementally maintainable materialized view +ROLLBACK; +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; +ERROR: UNION/INTERSECT/EXCEPT statements are not supported on incrementally maintainable materialized view +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; +ERROR: empty target list is not supported on incrementally maintainable materialized view +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; +ERROR: FOR UPDATE/SHARE clause is not supported on incrementally maintainable materialized view +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; +ERROR: column name __ivm_count__ is not supported on incrementally maintainable materialized view +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; +ERROR: GROUP BY expression not appearing in select list is not supported on incrementally maintainable materialized view +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); +ERROR: VALUES is not supported on incrementally maintainable materialized view +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +NOTICE: role "regress_ivm_admin" does not exist, skipping +DROP USER IF EXISTS regress_ivm_user; +NOTICE: role "regress_ivm_user" does not exist, skipping +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +NOTICE: could not create an index on materialized view "ivm_rls" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user +(1 row) + +RESET SESSION AUTHORIZATION; +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user + 3 | baz | regress_ivm_user +(2 rows) + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +-- +(1 row) + +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+-------+------------------ + 2 | bar | regress_ivm_user + 3 | baz | regress_ivm_user + 6 | corge | regress_ivm_user +(3 rows) + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +NOTICE: could not create an index on materialized view "ivm_rls2" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +RESET SESSION AUTHORIZATION; +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +-- +(1 row) + +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + id | data | owner | num +----+-------+------------------+--------- + 2 | bar | regress_ivm_user | two + 3 | baz_2 | regress_ivm_user | three_2 + 6 | corge | regress_ivm_user | six +(3 rows) + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +NOTICE: could not create an index on materialized view "mv_update_same" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + i +--- + 2 +(1 row) + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +NOTICE: created index "mv_self_ref_index" on materialized view "mv_self_ref" +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; + a | b +----+---- + 11 | + 12 | 11 + 13 | 12 +(3 rows) + +ROLLBACK; +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; +NOTICE: created index "mv_idx1_index" on materialized view "mv_idx1" +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; +NOTICE: created index "mv_idx2_index" on materialized view "mv_idx2" +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; +NOTICE: created index "mv_idx3_index" on materialized view "mv_idx3" +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +NOTICE: could not create an index on materialized view "mv_idx4" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; +NOTICE: could not create an index on materialized view "mv_idx5" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); +NOTICE: could not create an index on materialized view "mv_idx6" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ERROR: data type json has no default operator class for access method "btree" +ROLLBACK; +-- cleanup +DROP TABLE rls_tbl CASCADE; +NOTICE: drop cascades to 2 other objects +DETAIL: drop cascades to materialized view ivm_rls +drop cascades to materialized view ivm_rls2 +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; +DROP TABLE mv_base_b CASCADE; +NOTICE: drop cascades to 3 other objects +DETAIL: drop cascades to materialized view mv_ivm_1 +drop cascades to view b_view +drop cascades to materialized view b_mview +DROP TABLE mv_base_a CASCADE; diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index 8fa0a6c47fb..7caca5f64fd 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -77,6 +77,7 @@ test: brin_bloom brin_multi # Another group of parallel tests # ---------- test: create_table_like alter_generic alter_operator misc async dbsize merge misc_functions nls sysviews tsrf tid tidscan tidrangescan collate.utf8 collate.icu.utf8 incremental_sort create_role without_overlaps generated_virtual +test: incremental_matview # collate.linux.utf8 and collate.icu.utf8 tests cannot be run in parallel with each other # psql depends on create_am diff --git a/src/test/regress/sql/incremental_matview.sql b/src/test/regress/sql/incremental_matview.sql new file mode 100644 index 00000000000..2d55c393d6f --- /dev/null +++ b/src/test/regress/sql/incremental_matview.sql @@ -0,0 +1,580 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); + +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +REFRESH MATERIALIZED VIEW mv_ivm_1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; + +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; +ROLLBACK; + +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +DROP MATERIALIZED VIEW mv_ivm_rename; + +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +DROP MATERIALIZED VIEW mv_ivm_unique; + +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; + + +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +ROLLBACK; + +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +ROLLBACK; + +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +ROLLBACK; + +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +ROLLBACK; + +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +ROLLBACK; + +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min; + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); + +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; +ROLLBACK; + +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +SELECT * FROM mv_self ORDER BY v1; +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; +SELECT * FROM mv_self ORDER BY v1; + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + +ROLLBACK; + +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +SELECT * FROM mv ORDER BY v1; +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; +SELECT * FROM mv ORDER BY v1; +ROLLBACK; + +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +SELECT * FROM mv_ri ORDER BY i1; +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; +ROLLBACK; + +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +-- IMMV containing user defined type +BEGIN; + +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); + +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; + +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); + +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); + +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + +ROLLBACK; + +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; + +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; + +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; + +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; + +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; + +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); + +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; + +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); + +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ROLLBACK; + +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; + +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; + +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; + +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; + +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; + +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; + +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); + +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +DROP USER IF EXISTS regress_ivm_user; +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; + +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); + +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; + +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; + +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; +RESET SESSION AUTHORIZATION; + +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +RESET SESSION AUTHORIZATION; + +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; +ROLLBACK; + +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); + +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; + +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; + +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; + +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; + +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); + +ROLLBACK; + +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ROLLBACK; + +-- cleanup + +DROP TABLE rls_tbl CASCADE; +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; + +DROP TABLE mv_base_b CASCADE; +DROP TABLE mv_base_a CASCADE; -- 2.43.0 --Multipart=_Wed__1_Jul_2026_00_04_01_+0900_OVSy2WWK_9aByzDJ Content-Type: text/x-diff; name="v38-0009-Add-support-for-min-max-aggregates-for-IVM.patch" Content-Disposition: attachment; filename="v38-0009-Add-support-for-min-max-aggregates-for-IVM.patch" Content-Transfer-Encoding: 7bit ^ permalink raw reply [nested|flat] 78+ messages in thread
* [PATCH v38 10/11] Add regression tests for Incremental View Maintenance @ 2026-05-29 09:31 Yugo Nagata <[email protected]> 0 siblings, 0 replies; 78+ messages in thread From: Yugo Nagata @ 2026-05-29 09:31 UTC (permalink / raw) --- .../isolation/expected/ivm-create-insert.out | 285 +++++ .../isolation/expected/ivm-create-insert2.out | 305 +++++ .../isolation/expected/ivm-create-insert3.out | 305 +++++ .../isolation/expected/ivm-insert-insert.out | 497 ++++++++ .../isolation/expected/ivm-insert-insert2.out | 373 ++++++ .../isolation/expected/ivm-insert-insert3.out | 373 ++++++ .../isolation/expected/ivm-refresh-insert.out | 213 ++++ .../expected/ivm-refresh-insert2.out | 191 +++ .../expected/ivm-refresh-insert3.out | 191 +++ src/test/isolation/isolation_schedule | 9 + .../isolation/specs/ivm-create-insert.spec | 47 + .../isolation/specs/ivm-create-insert2.spec | 54 + .../isolation/specs/ivm-create-insert3.spec | 54 + .../isolation/specs/ivm-insert-insert.spec | 62 + .../isolation/specs/ivm-insert-insert2.spec | 62 + .../isolation/specs/ivm-insert-insert3.spec | 62 + .../isolation/specs/ivm-refresh-insert.spec | 46 + .../isolation/specs/ivm-refresh-insert2.spec | 46 + .../isolation/specs/ivm-refresh-insert3.spec | 46 + .../regress/expected/incremental_matview.out | 1100 +++++++++++++++++ src/test/regress/parallel_schedule | 1 + src/test/regress/sql/incremental_matview.sql | 580 +++++++++ 22 files changed, 4902 insertions(+) create mode 100644 src/test/isolation/expected/ivm-create-insert.out create mode 100644 src/test/isolation/expected/ivm-create-insert2.out create mode 100644 src/test/isolation/expected/ivm-create-insert3.out create mode 100644 src/test/isolation/expected/ivm-insert-insert.out create mode 100644 src/test/isolation/expected/ivm-insert-insert2.out create mode 100644 src/test/isolation/expected/ivm-insert-insert3.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert2.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert3.out create mode 100644 src/test/isolation/specs/ivm-create-insert.spec create mode 100644 src/test/isolation/specs/ivm-create-insert2.spec create mode 100644 src/test/isolation/specs/ivm-create-insert3.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert2.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert3.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert2.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert3.spec create mode 100644 src/test/regress/expected/incremental_matview.out create mode 100644 src/test/regress/sql/incremental_matview.sql diff --git a/src/test/isolation/expected/ivm-create-insert.out b/src/test/isolation/expected/ivm-create-insert.out new file mode 100644 index 00000000000..5da00043aba --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert.out @@ -0,0 +1,285 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-create-insert2.out b/src/test/isolation/expected/ivm-create-insert2.out new file mode 100644 index 00000000000..907d892c6d4 --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert2.out @@ -0,0 +1,305 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + diff --git a/src/test/isolation/expected/ivm-create-insert3.out b/src/test/isolation/expected/ivm-create-insert3.out new file mode 100644 index 00000000000..907d892c6d4 --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert3.out @@ -0,0 +1,305 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert.out b/src/test/isolation/expected/ivm-insert-insert.out new file mode 100644 index 00000000000..5ca4cfea677 --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert.out @@ -0,0 +1,497 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; <waiting ...> +step c1: COMMIT; +step update2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; <waiting ...> +step c1: COMMIT; +step update2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; <waiting ...> +step c2: COMMIT; +step update1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; <waiting ...> +step c2: COMMIT; +step update1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); <waiting ...> +step c1: COMMIT; +step insert2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); <waiting ...> +step c1: COMMIT; +step insert2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); <waiting ...> +step c2: COMMIT; +step insert1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); <waiting ...> +step c2: COMMIT; +step insert1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert2.out b/src/test/isolation/expected/ivm-insert-insert2.out new file mode 100644 index 00000000000..e1c66d4de5e --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert2.out @@ -0,0 +1,373 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert3.out b/src/test/isolation/expected/ivm-insert-insert3.out new file mode 100644 index 00000000000..e1c66d4de5e --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert3.out @@ -0,0 +1,373 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert.out b/src/test/isolation/expected/ivm-refresh-insert.out new file mode 100644 index 00000000000..a925938bf1c --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert.out @@ -0,0 +1,213 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert2.out b/src/test/isolation/expected/ivm-refresh-insert2.out new file mode 100644 index 00000000000..dc1b16ae34e --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert2.out @@ -0,0 +1,191 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert3.out b/src/test/isolation/expected/ivm-refresh-insert3.out new file mode 100644 index 00000000000..dc1b16ae34e --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert3.out @@ -0,0 +1,191 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/isolation_schedule b/src/test/isolation/isolation_schedule index b8ebe92553c..6b7e873b370 100644 --- a/src/test/isolation/isolation_schedule +++ b/src/test/isolation/isolation_schedule @@ -128,3 +128,12 @@ test: matview-write-skew test: lock-nowait test: for-portion-of test: ddl-dependency-locking +test: ivm-create-insert +test: ivm-create-insert2 +test: ivm-create-insert3 +test: ivm-insert-insert +test: ivm-insert-insert2 +test: ivm-insert-insert3 +test: ivm-refresh-insert +test: ivm-refresh-insert2 +test: ivm-refresh-insert3 diff --git a/src/test/isolation/specs/ivm-create-insert.spec b/src/test/isolation/specs/ivm-create-insert.spec new file mode 100644 index 00000000000..ccd6fd080a9 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert.spec @@ -0,0 +1,47 @@ +# Test interaction between concurrent transactions performing +# create and insert in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-create-insert2.spec b/src/test/isolation/specs/ivm-create-insert2.spec new file mode 100644 index 00000000000..02cec85ae07 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert2.spec @@ -0,0 +1,54 @@ +# Test interaction between concurrent transactions performing +# create and insert in REPEATABLE READ isolation level +# +# Note: +# In this isolation level, it is possible that create_immv could +# create an inconsistent view not including effects of a concurrent +# transaction. So, an warning message is raised to suggest using it +# in READ COMMITTED or executing refresh_immv to make sure to +# make the view contents consistent. + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-create-insert3.spec b/src/test/isolation/specs/ivm-create-insert3.spec new file mode 100644 index 00000000000..19ce03185a4 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert3.spec @@ -0,0 +1,54 @@ +# Test interaction between concurrent transactions performing +# create and insert in SERIALIZABLE isolation level +# +# Note: +# In this isolation level, it is possible that create_immv could +# create an inconsistent view not including effects of a concurrent +# transaction. So, an warning message is raised to suggest using it +# in READ COMMITTED or executing refresh_immv to make sure to +# make the view contents consistent. + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert.spec b/src/test/isolation/specs/ivm-insert-insert.spec new file mode 100644 index 00000000000..b8f794ca191 --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert2.spec b/src/test/isolation/specs/ivm-insert-insert2.spec new file mode 100644 index 00000000000..ed086d1ba1e --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert2.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in REPEATABLE READ isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert3.spec b/src/test/isolation/specs/ivm-insert-insert3.spec new file mode 100644 index 00000000000..b18bd121033 --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert3.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in SERIALIZABLE isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert.spec b/src/test/isolation/specs/ivm-refresh-insert.spec new file mode 100644 index 00000000000..d7181251962 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert2.spec b/src/test/isolation/specs/ivm-refresh-insert2.spec new file mode 100644 index 00000000000..f2d1d5013f2 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert2.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in REPEATABLE READ isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert3.spec b/src/test/isolation/specs/ivm-refresh-insert3.spec new file mode 100644 index 00000000000..0ec2b1d1de0 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert3.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in SERIALIZABLE isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/regress/expected/incremental_matview.out b/src/test/regress/expected/incremental_matview.out new file mode 100644 index 00000000000..f215aa88e48 --- /dev/null +++ b/src/test/regress/expected/incremental_matview.out @@ -0,0 +1,1100 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ERROR: materialized view "mv_ivm_1" has not been populated +HINT: Use the REFRESH MATERIALIZED VIEW command. +REFRESH MATERIALIZED VIEW mv_ivm_1; +NOTICE: could not create an index on materialized view "mv_ivm_1" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 17 +(1 row) + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 1 +(1 row) + +ROLLBACK; +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_rename_index" on materialized view "mv_ivm_rename" +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +ERROR: IVM column can not be renamed +DROP MATERIALIZED VIEW mv_ivm_rename; +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_unique_index" on materialized view "mv_ivm_unique" +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +ERROR: unique index creation on IVM columns is not supported +DROP MATERIALIZED VIEW mv_ivm_unique; +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +NOTICE: could not create an index on materialized view "mv_ivm_func" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +NOTICE: could not create an index on materialized view "mv_ivm_no_tbl" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_duplicate" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +NOTICE: created index "mv_ivm_distinct_index" on materialized view "mv_ivm_distinct" +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 20 + 30 + 40 + 50 +(6 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +ROLLBACK; +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 120 | 2 | 60.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+---------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 220 | 2 | 110.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 20 | 1 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 120 | 2 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; + sum | count +-----+------- +(0 rows) + +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; + i | sum | count +---+-----+------- +(0 rows) + +ROLLBACK; +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 150 | 5 | 30.0000000000000000 +(1 row) + +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 210 | 6 | 35.0000000000000000 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +NOTICE: created index "mv_ivm_avg_bug_index" on materialized view "mv_ivm_avg_bug" +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 3 | 3.3333333333333333 + 2 | 80 | 3 | 26.6666666666666667 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_min_max_index" on materialized view "mv_ivm_min_max" +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 10 + 2 | 20 | 20 + 3 | 30 | 30 + 4 | 40 | 40 + 5 | 50 | 50 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 12 + 2 | 20 | 22 + 3 | 30 | 32 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 11 | 12 + 2 | 20 | 22 + 3 | 30 | 31 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min_max" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 50 +(1 row) + +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 0 | 70 +(1 row) + +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 60 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + | +(1 row) + +ROLLBACK; +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min; + min +----- + 10 +(1 row) + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + min +----- + 20 +(1 row) + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; + min +----- + 30 +(1 row) + +ROLLBACK; +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | sum +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | b +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ERROR: too many column names were specified +ROLLBACK; +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +NOTICE: could not create an index on materialized view "mv_self" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +----+---- + 10 | 10 + 20 | 20 + 30 | 30 +(3 rows) + +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 30 | 30 + 40 | 40 + 200 | 200 +(3 rows) + +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 130 | 130 + 300 | 300 +(4 rows) + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 70 | 70 + 70 | 77 + 77 | 70 + 77 | 77 + 130 | 130 + 300 | 300 +(8 rows) + +ROLLBACK; +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY v1; + v1 | v2 +----+----- + 10 | 100 + 20 | 200 + 30 | 300 +(3 rows) + +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv ORDER BY v1; + v1 | v2 +------+----- + 10 | 100 + 11 | 100 + 1020 | 200 + 1020 | 222 +(4 rows) + +ROLLBACK; +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +NOTICE: created index "mv_ri_index" on materialized view "mv_ri" +SELECT * FROM mv_ri ORDER BY i1; + i1 | i2 +----+---- + 1 | 1 + 2 | 2 + 3 | 3 +(3 rows) + +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; + i1 | i2 +----+---- + 3 | 3 + 10 | 10 +(2 rows) + +ROLLBACK; +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | +(2 rows) + +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | 20 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i +--- +(0 rows) + +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; + i +--- + 1 + +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 30 + | 3 +(2 rows) + +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 300 + | 30 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 1 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 4 +(1 row) + +ROLLBACK; +-- IMMV containing user defined type +BEGIN; +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: return type mytype is only a shell +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: argument type mytype is only a shell +LINE 1: CREATE FUNCTION mytype_out(mytype) + ^ +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +NOTICE: could not create an index on materialized view "mv_mytype" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + x +--- + 1 +(1 row) + +ROLLBACK; +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +ERROR: OUTER JOIN is not supported on incrementally maintainable materialized view +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +ERROR: CTE is not supported on incrementally maintainable materialized view +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +ERROR: ORDER BY clause is not supported on incrementally maintainable materialized view +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; +ERROR: HAVING clause is not supported on incrementally maintainable materialized view +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; +ERROR: mutable function is not supported on incrementally maintainable materialized view +HINT: functions must be marked IMMUTABLE +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; +ERROR: LIMIT/OFFSET clause is not supported on incrementally maintainable materialized view +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; +ERROR: DISTINCT ON is not supported on incrementally maintainable materialized view +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); +ERROR: TABLESAMPLE clause is not supported on incrementally maintainable materialized view +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; +ERROR: window functions are not supported on incrementally maintainable materialized view +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +ERROR: aggregate function with FILTER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +ERROR: aggregate function with DISTINCT arguments is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +ERROR: aggregate function with ORDER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); +ERROR: GROUPING SETS, ROLLUP, or CUBE clauses is not supported on incrementally maintainable materialized view +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ERROR: inheritance parent is not supported on incrementally maintainable materialized view +ROLLBACK; +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; +ERROR: UNION/INTERSECT/EXCEPT statements are not supported on incrementally maintainable materialized view +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; +ERROR: empty target list is not supported on incrementally maintainable materialized view +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; +ERROR: FOR UPDATE/SHARE clause is not supported on incrementally maintainable materialized view +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; +ERROR: column name __ivm_count__ is not supported on incrementally maintainable materialized view +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; +ERROR: GROUP BY expression not appearing in select list is not supported on incrementally maintainable materialized view +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); +ERROR: VALUES is not supported on incrementally maintainable materialized view +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +NOTICE: role "regress_ivm_admin" does not exist, skipping +DROP USER IF EXISTS regress_ivm_user; +NOTICE: role "regress_ivm_user" does not exist, skipping +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +NOTICE: could not create an index on materialized view "ivm_rls" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user +(1 row) + +RESET SESSION AUTHORIZATION; +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user + 3 | baz | regress_ivm_user +(2 rows) + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +-- +(1 row) + +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+-------+------------------ + 2 | bar | regress_ivm_user + 3 | baz | regress_ivm_user + 6 | corge | regress_ivm_user +(3 rows) + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +NOTICE: could not create an index on materialized view "ivm_rls2" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +RESET SESSION AUTHORIZATION; +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +-- +(1 row) + +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + id | data | owner | num +----+-------+------------------+--------- + 2 | bar | regress_ivm_user | two + 3 | baz_2 | regress_ivm_user | three_2 + 6 | corge | regress_ivm_user | six +(3 rows) + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +NOTICE: could not create an index on materialized view "mv_update_same" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + i +--- + 2 +(1 row) + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +NOTICE: created index "mv_self_ref_index" on materialized view "mv_self_ref" +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; + a | b +----+---- + 11 | + 12 | 11 + 13 | 12 +(3 rows) + +ROLLBACK; +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; +NOTICE: created index "mv_idx1_index" on materialized view "mv_idx1" +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; +NOTICE: created index "mv_idx2_index" on materialized view "mv_idx2" +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; +NOTICE: created index "mv_idx3_index" on materialized view "mv_idx3" +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +NOTICE: could not create an index on materialized view "mv_idx4" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; +NOTICE: could not create an index on materialized view "mv_idx5" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); +NOTICE: could not create an index on materialized view "mv_idx6" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ERROR: data type json has no default operator class for access method "btree" +ROLLBACK; +-- cleanup +DROP TABLE rls_tbl CASCADE; +NOTICE: drop cascades to 2 other objects +DETAIL: drop cascades to materialized view ivm_rls +drop cascades to materialized view ivm_rls2 +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; +DROP TABLE mv_base_b CASCADE; +NOTICE: drop cascades to 3 other objects +DETAIL: drop cascades to materialized view mv_ivm_1 +drop cascades to view b_view +drop cascades to materialized view b_mview +DROP TABLE mv_base_a CASCADE; diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index 8fa0a6c47fb..7caca5f64fd 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -77,6 +77,7 @@ test: brin_bloom brin_multi # Another group of parallel tests # ---------- test: create_table_like alter_generic alter_operator misc async dbsize merge misc_functions nls sysviews tsrf tid tidscan tidrangescan collate.utf8 collate.icu.utf8 incremental_sort create_role without_overlaps generated_virtual +test: incremental_matview # collate.linux.utf8 and collate.icu.utf8 tests cannot be run in parallel with each other # psql depends on create_am diff --git a/src/test/regress/sql/incremental_matview.sql b/src/test/regress/sql/incremental_matview.sql new file mode 100644 index 00000000000..2d55c393d6f --- /dev/null +++ b/src/test/regress/sql/incremental_matview.sql @@ -0,0 +1,580 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); + +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +REFRESH MATERIALIZED VIEW mv_ivm_1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; + +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; +ROLLBACK; + +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +DROP MATERIALIZED VIEW mv_ivm_rename; + +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +DROP MATERIALIZED VIEW mv_ivm_unique; + +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; + + +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +ROLLBACK; + +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +ROLLBACK; + +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +ROLLBACK; + +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +ROLLBACK; + +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +ROLLBACK; + +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min; + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); + +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; +ROLLBACK; + +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +SELECT * FROM mv_self ORDER BY v1; +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; +SELECT * FROM mv_self ORDER BY v1; + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + +ROLLBACK; + +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +SELECT * FROM mv ORDER BY v1; +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; +SELECT * FROM mv ORDER BY v1; +ROLLBACK; + +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +SELECT * FROM mv_ri ORDER BY i1; +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; +ROLLBACK; + +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +-- IMMV containing user defined type +BEGIN; + +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); + +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; + +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); + +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); + +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + +ROLLBACK; + +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; + +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; + +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; + +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; + +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; + +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); + +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; + +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); + +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ROLLBACK; + +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; + +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; + +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; + +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; + +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; + +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; + +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); + +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +DROP USER IF EXISTS regress_ivm_user; +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; + +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); + +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; + +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; + +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; +RESET SESSION AUTHORIZATION; + +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +RESET SESSION AUTHORIZATION; + +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; +ROLLBACK; + +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); + +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; + +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; + +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; + +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; + +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); + +ROLLBACK; + +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ROLLBACK; + +-- cleanup + +DROP TABLE rls_tbl CASCADE; +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; + +DROP TABLE mv_base_b CASCADE; +DROP TABLE mv_base_a CASCADE; -- 2.43.0 --Multipart=_Wed__1_Jul_2026_00_04_01_+0900_OVSy2WWK_9aByzDJ Content-Type: text/x-diff; name="v38-0009-Add-support-for-min-max-aggregates-for-IVM.patch" Content-Disposition: attachment; filename="v38-0009-Add-support-for-min-max-aggregates-for-IVM.patch" Content-Transfer-Encoding: 7bit ^ permalink raw reply [nested|flat] 78+ messages in thread
* [PATCH v39 7/8] Add regression tests for Incremental View Maintenance @ 2026-05-29 09:31 Yugo Nagata <[email protected]> 0 siblings, 0 replies; 78+ messages in thread From: Yugo Nagata @ 2026-05-29 09:31 UTC (permalink / raw) --- .../isolation/expected/ivm-create-insert.out | 285 ++++++++ .../isolation/expected/ivm-create-insert2.out | 305 ++++++++ .../isolation/expected/ivm-create-insert3.out | 305 ++++++++ .../isolation/expected/ivm-insert-insert.out | 497 +++++++++++++ .../isolation/expected/ivm-insert-insert2.out | 373 ++++++++++ .../isolation/expected/ivm-insert-insert3.out | 373 ++++++++++ .../isolation/expected/ivm-refresh-insert.out | 213 ++++++ .../expected/ivm-refresh-insert2.out | 191 +++++ .../expected/ivm-refresh-insert3.out | 191 +++++ src/test/isolation/isolation_schedule | 9 + .../isolation/specs/ivm-create-insert.spec | 47 ++ .../isolation/specs/ivm-create-insert2.spec | 54 ++ .../isolation/specs/ivm-create-insert3.spec | 54 ++ .../isolation/specs/ivm-insert-insert.spec | 62 ++ .../isolation/specs/ivm-insert-insert2.spec | 62 ++ .../isolation/specs/ivm-insert-insert3.spec | 62 ++ .../isolation/specs/ivm-refresh-insert.spec | 46 ++ .../isolation/specs/ivm-refresh-insert2.spec | 46 ++ .../isolation/specs/ivm-refresh-insert3.spec | 46 ++ .../regress/expected/incremental_matview.out | 667 ++++++++++++++++++ src/test/regress/parallel_schedule | 1 + src/test/regress/sql/incremental_matview.sql | 407 +++++++++++ 22 files changed, 4296 insertions(+) create mode 100644 src/test/isolation/expected/ivm-create-insert.out create mode 100644 src/test/isolation/expected/ivm-create-insert2.out create mode 100644 src/test/isolation/expected/ivm-create-insert3.out create mode 100644 src/test/isolation/expected/ivm-insert-insert.out create mode 100644 src/test/isolation/expected/ivm-insert-insert2.out create mode 100644 src/test/isolation/expected/ivm-insert-insert3.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert2.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert3.out create mode 100644 src/test/isolation/specs/ivm-create-insert.spec create mode 100644 src/test/isolation/specs/ivm-create-insert2.spec create mode 100644 src/test/isolation/specs/ivm-create-insert3.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert2.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert3.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert2.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert3.spec create mode 100644 src/test/regress/expected/incremental_matview.out create mode 100644 src/test/regress/sql/incremental_matview.sql diff --git a/src/test/isolation/expected/ivm-create-insert.out b/src/test/isolation/expected/ivm-create-insert.out new file mode 100644 index 00000000000..5da00043aba --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert.out @@ -0,0 +1,285 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-create-insert2.out b/src/test/isolation/expected/ivm-create-insert2.out new file mode 100644 index 00000000000..907d892c6d4 --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert2.out @@ -0,0 +1,305 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + diff --git a/src/test/isolation/expected/ivm-create-insert3.out b/src/test/isolation/expected/ivm-create-insert3.out new file mode 100644 index 00000000000..907d892c6d4 --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert3.out @@ -0,0 +1,305 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert.out b/src/test/isolation/expected/ivm-insert-insert.out new file mode 100644 index 00000000000..5ca4cfea677 --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert.out @@ -0,0 +1,497 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; <waiting ...> +step c1: COMMIT; +step update2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; <waiting ...> +step c1: COMMIT; +step update2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; <waiting ...> +step c2: COMMIT; +step update1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; <waiting ...> +step c2: COMMIT; +step update1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); <waiting ...> +step c1: COMMIT; +step insert2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); <waiting ...> +step c1: COMMIT; +step insert2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); <waiting ...> +step c2: COMMIT; +step insert1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); <waiting ...> +step c2: COMMIT; +step insert1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert2.out b/src/test/isolation/expected/ivm-insert-insert2.out new file mode 100644 index 00000000000..e1c66d4de5e --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert2.out @@ -0,0 +1,373 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert3.out b/src/test/isolation/expected/ivm-insert-insert3.out new file mode 100644 index 00000000000..e1c66d4de5e --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert3.out @@ -0,0 +1,373 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert.out b/src/test/isolation/expected/ivm-refresh-insert.out new file mode 100644 index 00000000000..a925938bf1c --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert.out @@ -0,0 +1,213 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert2.out b/src/test/isolation/expected/ivm-refresh-insert2.out new file mode 100644 index 00000000000..dc1b16ae34e --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert2.out @@ -0,0 +1,191 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert3.out b/src/test/isolation/expected/ivm-refresh-insert3.out new file mode 100644 index 00000000000..dc1b16ae34e --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert3.out @@ -0,0 +1,191 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/isolation_schedule b/src/test/isolation/isolation_schedule index b8ebe92553c..6b7e873b370 100644 --- a/src/test/isolation/isolation_schedule +++ b/src/test/isolation/isolation_schedule @@ -128,3 +128,12 @@ test: matview-write-skew test: lock-nowait test: for-portion-of test: ddl-dependency-locking +test: ivm-create-insert +test: ivm-create-insert2 +test: ivm-create-insert3 +test: ivm-insert-insert +test: ivm-insert-insert2 +test: ivm-insert-insert3 +test: ivm-refresh-insert +test: ivm-refresh-insert2 +test: ivm-refresh-insert3 diff --git a/src/test/isolation/specs/ivm-create-insert.spec b/src/test/isolation/specs/ivm-create-insert.spec new file mode 100644 index 00000000000..ccd6fd080a9 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert.spec @@ -0,0 +1,47 @@ +# Test interaction between concurrent transactions performing +# create and insert in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-create-insert2.spec b/src/test/isolation/specs/ivm-create-insert2.spec new file mode 100644 index 00000000000..02cec85ae07 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert2.spec @@ -0,0 +1,54 @@ +# Test interaction between concurrent transactions performing +# create and insert in REPEATABLE READ isolation level +# +# Note: +# In this isolation level, it is possible that create_immv could +# create an inconsistent view not including effects of a concurrent +# transaction. So, an warning message is raised to suggest using it +# in READ COMMITTED or executing refresh_immv to make sure to +# make the view contents consistent. + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-create-insert3.spec b/src/test/isolation/specs/ivm-create-insert3.spec new file mode 100644 index 00000000000..19ce03185a4 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert3.spec @@ -0,0 +1,54 @@ +# Test interaction between concurrent transactions performing +# create and insert in SERIALIZABLE isolation level +# +# Note: +# In this isolation level, it is possible that create_immv could +# create an inconsistent view not including effects of a concurrent +# transaction. So, an warning message is raised to suggest using it +# in READ COMMITTED or executing refresh_immv to make sure to +# make the view contents consistent. + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert.spec b/src/test/isolation/specs/ivm-insert-insert.spec new file mode 100644 index 00000000000..b8f794ca191 --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert2.spec b/src/test/isolation/specs/ivm-insert-insert2.spec new file mode 100644 index 00000000000..ed086d1ba1e --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert2.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in REPEATABLE READ isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert3.spec b/src/test/isolation/specs/ivm-insert-insert3.spec new file mode 100644 index 00000000000..b18bd121033 --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert3.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in SERIALIZABLE isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert.spec b/src/test/isolation/specs/ivm-refresh-insert.spec new file mode 100644 index 00000000000..d7181251962 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert2.spec b/src/test/isolation/specs/ivm-refresh-insert2.spec new file mode 100644 index 00000000000..f2d1d5013f2 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert2.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in REPEATABLE READ isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert3.spec b/src/test/isolation/specs/ivm-refresh-insert3.spec new file mode 100644 index 00000000000..0ec2b1d1de0 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert3.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in SERIALIZABLE isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/regress/expected/incremental_matview.out b/src/test/regress/expected/incremental_matview.out new file mode 100644 index 00000000000..c7fd19fdca3 --- /dev/null +++ b/src/test/regress/expected/incremental_matview.out @@ -0,0 +1,667 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ERROR: materialized view "mv_ivm_1" has not been populated +HINT: Use the REFRESH MATERIALIZED VIEW command. +REFRESH MATERIALIZED VIEW mv_ivm_1; +NOTICE: could not create an index on materialized view "mv_ivm_1" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 17 +(1 row) + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 1 +(1 row) + +ROLLBACK; +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- DISTINCT not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT * FROM mv_base_a; +ERROR: DISTINCT is not supported on incrementally maintainable materialized view +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +NOTICE: could not create an index on materialized view "mv_ivm_func" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +NOTICE: could not create an index on materialized view "mv_ivm_no_tbl" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- result of materialized view have duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_duplicate" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 20 + 30 + 40 + 50 +(6 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +ROLLBACK; +-- aggregate not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +ERROR: aggregate function is not supported on incrementally maintainable materialized view +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +NOTICE: could not create an index on materialized view "mv_self" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +----+---- + 10 | 10 + 20 | 20 + 30 | 30 +(3 rows) + +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 30 | 30 + 40 | 40 + 200 | 200 +(3 rows) + +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 130 | 130 + 300 | 300 +(4 rows) + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 70 | 70 + 70 | 77 + 77 | 70 + 77 | 77 + 130 | 130 + 300 | 300 +(8 rows) + +ROLLBACK; +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY v1; + v1 | v2 +----+----- + 10 | 100 + 20 | 200 + 30 | 300 +(3 rows) + +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv ORDER BY v1; + v1 | v2 +------+----- + 10 | 100 + 11 | 100 + 1020 | 200 + 1020 | 222 +(4 rows) + +ROLLBACK; +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +NOTICE: created index "mv_ri_index" on materialized view "mv_ri" +SELECT * FROM mv_ri ORDER BY i1; + i1 | i2 +----+---- + 1 | 1 + 2 | 2 + 3 | 3 +(3 rows) + +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; + i1 | i2 +----+---- + 3 | 3 + 10 | 10 +(2 rows) + +ROLLBACK; +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | +(2 rows) + +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | 20 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i +--- +(0 rows) + +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; + i +--- + 1 + +(2 rows) + +ROLLBACK; +-- IMMV containing user defined type +BEGIN; +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: return type mytype is only a shell +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: argument type mytype is only a shell +LINE 1: CREATE FUNCTION mytype_out(mytype) + ^ +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +NOTICE: could not create an index on materialized view "mv_mytype" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + x +--- + 1 +(1 row) + +ROLLBACK; +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +ERROR: OUTER JOIN is not supported on incrementally maintainable materialized view +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +ERROR: CTE is not supported on incrementally maintainable materialized view +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +ERROR: ORDER BY clause is not supported on incrementally maintainable materialized view +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; +ERROR: HAVING clause is not supported on incrementally maintainable materialized view +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; +ERROR: mutable function is not supported on incrementally maintainable materialized view +HINT: functions must be marked IMMUTABLE +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; +ERROR: LIMIT/OFFSET clause is not supported on incrementally maintainable materialized view +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; +ERROR: DISTINCT is not supported on incrementally maintainable materialized view +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); +ERROR: TABLESAMPLE clause is not supported on incrementally maintainable materialized view +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; +ERROR: window functions are not supported on incrementally maintainable materialized view +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ERROR: inheritance parent is not supported on incrementally maintainable materialized view +ROLLBACK; +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; +ERROR: UNION/INTERSECT/EXCEPT statements are not supported on incrementally maintainable materialized view +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; +ERROR: empty target list is not supported on incrementally maintainable materialized view +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; +ERROR: FOR UPDATE/SHARE clause is not supported on incrementally maintainable materialized view +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; +ERROR: column name __ivm_count__ is not supported on incrementally maintainable materialized view +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; +ERROR: aggregate function is not supported on incrementally maintainable materialized view +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); +ERROR: VALUES is not supported on incrementally maintainable materialized view +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +NOTICE: role "regress_ivm_admin" does not exist, skipping +DROP USER IF EXISTS regress_ivm_user; +NOTICE: role "regress_ivm_user" does not exist, skipping +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +NOTICE: could not create an index on materialized view "ivm_rls" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user +(1 row) + +RESET SESSION AUTHORIZATION; +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user + 3 | baz | regress_ivm_user +(2 rows) + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +-- +(1 row) + +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+-------+------------------ + 2 | bar | regress_ivm_user + 3 | baz | regress_ivm_user + 6 | corge | regress_ivm_user +(3 rows) + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +NOTICE: could not create an index on materialized view "ivm_rls2" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +RESET SESSION AUTHORIZATION; +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +-- +(1 row) + +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + id | data | owner | num +----+-------+------------------+--------- + 2 | bar | regress_ivm_user | two + 3 | baz_2 | regress_ivm_user | three_2 + 6 | corge | regress_ivm_user | six +(3 rows) + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +NOTICE: could not create an index on materialized view "mv_update_same" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + i +--- + 2 +(1 row) + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +NOTICE: created index "mv_self_ref_index" on materialized view "mv_self_ref" +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; + a | b +----+---- + 11 | + 12 | 11 + 13 | 12 +(3 rows) + +ROLLBACK; +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; +NOTICE: created index "mv_idx3_index" on materialized view "mv_idx3" +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +NOTICE: could not create an index on materialized view "mv_idx4" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; +NOTICE: could not create an index on materialized view "mv_idx5" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); +NOTICE: could not create an index on materialized view "mv_idx6" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ERROR: data type json has no default operator class for access method "btree" +ROLLBACK; +-- cleanup +DROP TABLE rls_tbl CASCADE; +NOTICE: drop cascades to 2 other objects +DETAIL: drop cascades to materialized view ivm_rls +drop cascades to materialized view ivm_rls2 +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; +DROP TABLE mv_base_b CASCADE; +NOTICE: drop cascades to 3 other objects +DETAIL: drop cascades to materialized view mv_ivm_1 +drop cascades to view b_view +drop cascades to materialized view b_mview +DROP TABLE mv_base_a CASCADE; diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index 8fa0a6c47fb..7caca5f64fd 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -77,6 +77,7 @@ test: brin_bloom brin_multi # Another group of parallel tests # ---------- test: create_table_like alter_generic alter_operator misc async dbsize merge misc_functions nls sysviews tsrf tid tidscan tidrangescan collate.utf8 collate.icu.utf8 incremental_sort create_role without_overlaps generated_virtual +test: incremental_matview # collate.linux.utf8 and collate.icu.utf8 tests cannot be run in parallel with each other # psql depends on create_am diff --git a/src/test/regress/sql/incremental_matview.sql b/src/test/regress/sql/incremental_matview.sql new file mode 100644 index 00000000000..7313ad82f3e --- /dev/null +++ b/src/test/regress/sql/incremental_matview.sql @@ -0,0 +1,407 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); + +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +REFRESH MATERIALIZED VIEW mv_ivm_1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; + +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; +ROLLBACK; + +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- DISTINCT not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT * FROM mv_base_a; + +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; + + +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +ROLLBACK; + +-- result of materialized view have duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +ROLLBACK; + +-- aggregate not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; + +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +SELECT * FROM mv_self ORDER BY v1; +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; +SELECT * FROM mv_self ORDER BY v1; + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + +ROLLBACK; + +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +SELECT * FROM mv ORDER BY v1; +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; +SELECT * FROM mv ORDER BY v1; +ROLLBACK; + +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +SELECT * FROM mv_ri ORDER BY i1; +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; +ROLLBACK; + +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +-- IMMV containing user defined type +BEGIN; + +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); + +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; + +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); + +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); + +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + +ROLLBACK; + +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; + +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; + +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; + +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; + +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; + +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); + +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; + +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ROLLBACK; + +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; + +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; + +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; + +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; + +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; + +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); + +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +DROP USER IF EXISTS regress_ivm_user; +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; + +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); + +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; + +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; + +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; +RESET SESSION AUTHORIZATION; + +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +RESET SESSION AUTHORIZATION; + +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; +ROLLBACK; + +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); + +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; + +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; + +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); + +ROLLBACK; + +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ROLLBACK; + +-- cleanup + +DROP TABLE rls_tbl CASCADE; +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; + +DROP TABLE mv_base_b CASCADE; +DROP TABLE mv_base_a CASCADE; -- 2.43.0 --Multipart=_Fri__3_Jul_2026_19_11_16_+0900_CskxSIu_iGcDMEyM Content-Type: text/x-diff; name="v39-0006-Add-Incremental-View-Maintenance-support.patch" Content-Disposition: attachment; filename="v39-0006-Add-Incremental-View-Maintenance-support.patch" Content-Transfer-Encoding: 7bit ^ permalink raw reply [nested|flat] 78+ messages in thread
* [PATCH v38 10/11] Add regression tests for Incremental View Maintenance @ 2026-05-29 09:31 Yugo Nagata <[email protected]> 0 siblings, 0 replies; 78+ messages in thread From: Yugo Nagata @ 2026-05-29 09:31 UTC (permalink / raw) --- .../isolation/expected/ivm-create-insert.out | 285 +++++ .../isolation/expected/ivm-create-insert2.out | 305 +++++ .../isolation/expected/ivm-create-insert3.out | 305 +++++ .../isolation/expected/ivm-insert-insert.out | 497 ++++++++ .../isolation/expected/ivm-insert-insert2.out | 373 ++++++ .../isolation/expected/ivm-insert-insert3.out | 373 ++++++ .../isolation/expected/ivm-refresh-insert.out | 213 ++++ .../expected/ivm-refresh-insert2.out | 191 +++ .../expected/ivm-refresh-insert3.out | 191 +++ src/test/isolation/isolation_schedule | 9 + .../isolation/specs/ivm-create-insert.spec | 47 + .../isolation/specs/ivm-create-insert2.spec | 54 + .../isolation/specs/ivm-create-insert3.spec | 54 + .../isolation/specs/ivm-insert-insert.spec | 62 + .../isolation/specs/ivm-insert-insert2.spec | 62 + .../isolation/specs/ivm-insert-insert3.spec | 62 + .../isolation/specs/ivm-refresh-insert.spec | 46 + .../isolation/specs/ivm-refresh-insert2.spec | 46 + .../isolation/specs/ivm-refresh-insert3.spec | 46 + .../regress/expected/incremental_matview.out | 1100 +++++++++++++++++ src/test/regress/parallel_schedule | 1 + src/test/regress/sql/incremental_matview.sql | 580 +++++++++ 22 files changed, 4902 insertions(+) create mode 100644 src/test/isolation/expected/ivm-create-insert.out create mode 100644 src/test/isolation/expected/ivm-create-insert2.out create mode 100644 src/test/isolation/expected/ivm-create-insert3.out create mode 100644 src/test/isolation/expected/ivm-insert-insert.out create mode 100644 src/test/isolation/expected/ivm-insert-insert2.out create mode 100644 src/test/isolation/expected/ivm-insert-insert3.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert2.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert3.out create mode 100644 src/test/isolation/specs/ivm-create-insert.spec create mode 100644 src/test/isolation/specs/ivm-create-insert2.spec create mode 100644 src/test/isolation/specs/ivm-create-insert3.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert2.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert3.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert2.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert3.spec create mode 100644 src/test/regress/expected/incremental_matview.out create mode 100644 src/test/regress/sql/incremental_matview.sql diff --git a/src/test/isolation/expected/ivm-create-insert.out b/src/test/isolation/expected/ivm-create-insert.out new file mode 100644 index 00000000000..5da00043aba --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert.out @@ -0,0 +1,285 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-create-insert2.out b/src/test/isolation/expected/ivm-create-insert2.out new file mode 100644 index 00000000000..907d892c6d4 --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert2.out @@ -0,0 +1,305 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + diff --git a/src/test/isolation/expected/ivm-create-insert3.out b/src/test/isolation/expected/ivm-create-insert3.out new file mode 100644 index 00000000000..907d892c6d4 --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert3.out @@ -0,0 +1,305 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert.out b/src/test/isolation/expected/ivm-insert-insert.out new file mode 100644 index 00000000000..5ca4cfea677 --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert.out @@ -0,0 +1,497 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; <waiting ...> +step c1: COMMIT; +step update2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; <waiting ...> +step c1: COMMIT; +step update2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; <waiting ...> +step c2: COMMIT; +step update1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; <waiting ...> +step c2: COMMIT; +step update1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); <waiting ...> +step c1: COMMIT; +step insert2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); <waiting ...> +step c1: COMMIT; +step insert2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); <waiting ...> +step c2: COMMIT; +step insert1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); <waiting ...> +step c2: COMMIT; +step insert1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert2.out b/src/test/isolation/expected/ivm-insert-insert2.out new file mode 100644 index 00000000000..e1c66d4de5e --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert2.out @@ -0,0 +1,373 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert3.out b/src/test/isolation/expected/ivm-insert-insert3.out new file mode 100644 index 00000000000..e1c66d4de5e --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert3.out @@ -0,0 +1,373 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert.out b/src/test/isolation/expected/ivm-refresh-insert.out new file mode 100644 index 00000000000..a925938bf1c --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert.out @@ -0,0 +1,213 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert2.out b/src/test/isolation/expected/ivm-refresh-insert2.out new file mode 100644 index 00000000000..dc1b16ae34e --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert2.out @@ -0,0 +1,191 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert3.out b/src/test/isolation/expected/ivm-refresh-insert3.out new file mode 100644 index 00000000000..dc1b16ae34e --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert3.out @@ -0,0 +1,191 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/isolation_schedule b/src/test/isolation/isolation_schedule index b8ebe92553c..6b7e873b370 100644 --- a/src/test/isolation/isolation_schedule +++ b/src/test/isolation/isolation_schedule @@ -128,3 +128,12 @@ test: matview-write-skew test: lock-nowait test: for-portion-of test: ddl-dependency-locking +test: ivm-create-insert +test: ivm-create-insert2 +test: ivm-create-insert3 +test: ivm-insert-insert +test: ivm-insert-insert2 +test: ivm-insert-insert3 +test: ivm-refresh-insert +test: ivm-refresh-insert2 +test: ivm-refresh-insert3 diff --git a/src/test/isolation/specs/ivm-create-insert.spec b/src/test/isolation/specs/ivm-create-insert.spec new file mode 100644 index 00000000000..ccd6fd080a9 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert.spec @@ -0,0 +1,47 @@ +# Test interaction between concurrent transactions performing +# create and insert in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-create-insert2.spec b/src/test/isolation/specs/ivm-create-insert2.spec new file mode 100644 index 00000000000..02cec85ae07 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert2.spec @@ -0,0 +1,54 @@ +# Test interaction between concurrent transactions performing +# create and insert in REPEATABLE READ isolation level +# +# Note: +# In this isolation level, it is possible that create_immv could +# create an inconsistent view not including effects of a concurrent +# transaction. So, an warning message is raised to suggest using it +# in READ COMMITTED or executing refresh_immv to make sure to +# make the view contents consistent. + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-create-insert3.spec b/src/test/isolation/specs/ivm-create-insert3.spec new file mode 100644 index 00000000000..19ce03185a4 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert3.spec @@ -0,0 +1,54 @@ +# Test interaction between concurrent transactions performing +# create and insert in SERIALIZABLE isolation level +# +# Note: +# In this isolation level, it is possible that create_immv could +# create an inconsistent view not including effects of a concurrent +# transaction. So, an warning message is raised to suggest using it +# in READ COMMITTED or executing refresh_immv to make sure to +# make the view contents consistent. + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert.spec b/src/test/isolation/specs/ivm-insert-insert.spec new file mode 100644 index 00000000000..b8f794ca191 --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert2.spec b/src/test/isolation/specs/ivm-insert-insert2.spec new file mode 100644 index 00000000000..ed086d1ba1e --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert2.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in REPEATABLE READ isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert3.spec b/src/test/isolation/specs/ivm-insert-insert3.spec new file mode 100644 index 00000000000..b18bd121033 --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert3.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in SERIALIZABLE isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert.spec b/src/test/isolation/specs/ivm-refresh-insert.spec new file mode 100644 index 00000000000..d7181251962 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert2.spec b/src/test/isolation/specs/ivm-refresh-insert2.spec new file mode 100644 index 00000000000..f2d1d5013f2 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert2.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in REPEATABLE READ isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert3.spec b/src/test/isolation/specs/ivm-refresh-insert3.spec new file mode 100644 index 00000000000..0ec2b1d1de0 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert3.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in SERIALIZABLE isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/regress/expected/incremental_matview.out b/src/test/regress/expected/incremental_matview.out new file mode 100644 index 00000000000..f215aa88e48 --- /dev/null +++ b/src/test/regress/expected/incremental_matview.out @@ -0,0 +1,1100 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ERROR: materialized view "mv_ivm_1" has not been populated +HINT: Use the REFRESH MATERIALIZED VIEW command. +REFRESH MATERIALIZED VIEW mv_ivm_1; +NOTICE: could not create an index on materialized view "mv_ivm_1" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 17 +(1 row) + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 1 +(1 row) + +ROLLBACK; +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_rename_index" on materialized view "mv_ivm_rename" +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +ERROR: IVM column can not be renamed +DROP MATERIALIZED VIEW mv_ivm_rename; +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_unique_index" on materialized view "mv_ivm_unique" +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +ERROR: unique index creation on IVM columns is not supported +DROP MATERIALIZED VIEW mv_ivm_unique; +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +NOTICE: could not create an index on materialized view "mv_ivm_func" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +NOTICE: could not create an index on materialized view "mv_ivm_no_tbl" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_duplicate" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +NOTICE: created index "mv_ivm_distinct_index" on materialized view "mv_ivm_distinct" +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 20 + 30 + 40 + 50 +(6 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +ROLLBACK; +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 120 | 2 | 60.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+---------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 220 | 2 | 110.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 20 | 1 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 120 | 2 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; + sum | count +-----+------- +(0 rows) + +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; + i | sum | count +---+-----+------- +(0 rows) + +ROLLBACK; +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 150 | 5 | 30.0000000000000000 +(1 row) + +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 210 | 6 | 35.0000000000000000 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +NOTICE: created index "mv_ivm_avg_bug_index" on materialized view "mv_ivm_avg_bug" +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 3 | 3.3333333333333333 + 2 | 80 | 3 | 26.6666666666666667 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_min_max_index" on materialized view "mv_ivm_min_max" +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 10 + 2 | 20 | 20 + 3 | 30 | 30 + 4 | 40 | 40 + 5 | 50 | 50 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 12 + 2 | 20 | 22 + 3 | 30 | 32 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 11 | 12 + 2 | 20 | 22 + 3 | 30 | 31 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min_max" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 50 +(1 row) + +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 0 | 70 +(1 row) + +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 60 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + | +(1 row) + +ROLLBACK; +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min; + min +----- + 10 +(1 row) + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + min +----- + 20 +(1 row) + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; + min +----- + 30 +(1 row) + +ROLLBACK; +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | sum +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | b +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ERROR: too many column names were specified +ROLLBACK; +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +NOTICE: could not create an index on materialized view "mv_self" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +----+---- + 10 | 10 + 20 | 20 + 30 | 30 +(3 rows) + +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 30 | 30 + 40 | 40 + 200 | 200 +(3 rows) + +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 130 | 130 + 300 | 300 +(4 rows) + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 70 | 70 + 70 | 77 + 77 | 70 + 77 | 77 + 130 | 130 + 300 | 300 +(8 rows) + +ROLLBACK; +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY v1; + v1 | v2 +----+----- + 10 | 100 + 20 | 200 + 30 | 300 +(3 rows) + +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv ORDER BY v1; + v1 | v2 +------+----- + 10 | 100 + 11 | 100 + 1020 | 200 + 1020 | 222 +(4 rows) + +ROLLBACK; +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +NOTICE: created index "mv_ri_index" on materialized view "mv_ri" +SELECT * FROM mv_ri ORDER BY i1; + i1 | i2 +----+---- + 1 | 1 + 2 | 2 + 3 | 3 +(3 rows) + +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; + i1 | i2 +----+---- + 3 | 3 + 10 | 10 +(2 rows) + +ROLLBACK; +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | +(2 rows) + +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | 20 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i +--- +(0 rows) + +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; + i +--- + 1 + +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 30 + | 3 +(2 rows) + +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 300 + | 30 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 1 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 4 +(1 row) + +ROLLBACK; +-- IMMV containing user defined type +BEGIN; +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: return type mytype is only a shell +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: argument type mytype is only a shell +LINE 1: CREATE FUNCTION mytype_out(mytype) + ^ +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +NOTICE: could not create an index on materialized view "mv_mytype" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + x +--- + 1 +(1 row) + +ROLLBACK; +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +ERROR: OUTER JOIN is not supported on incrementally maintainable materialized view +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +ERROR: CTE is not supported on incrementally maintainable materialized view +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +ERROR: ORDER BY clause is not supported on incrementally maintainable materialized view +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; +ERROR: HAVING clause is not supported on incrementally maintainable materialized view +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; +ERROR: mutable function is not supported on incrementally maintainable materialized view +HINT: functions must be marked IMMUTABLE +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; +ERROR: LIMIT/OFFSET clause is not supported on incrementally maintainable materialized view +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; +ERROR: DISTINCT ON is not supported on incrementally maintainable materialized view +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); +ERROR: TABLESAMPLE clause is not supported on incrementally maintainable materialized view +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; +ERROR: window functions are not supported on incrementally maintainable materialized view +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +ERROR: aggregate function with FILTER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +ERROR: aggregate function with DISTINCT arguments is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +ERROR: aggregate function with ORDER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); +ERROR: GROUPING SETS, ROLLUP, or CUBE clauses is not supported on incrementally maintainable materialized view +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ERROR: inheritance parent is not supported on incrementally maintainable materialized view +ROLLBACK; +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; +ERROR: UNION/INTERSECT/EXCEPT statements are not supported on incrementally maintainable materialized view +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; +ERROR: empty target list is not supported on incrementally maintainable materialized view +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; +ERROR: FOR UPDATE/SHARE clause is not supported on incrementally maintainable materialized view +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; +ERROR: column name __ivm_count__ is not supported on incrementally maintainable materialized view +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; +ERROR: GROUP BY expression not appearing in select list is not supported on incrementally maintainable materialized view +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); +ERROR: VALUES is not supported on incrementally maintainable materialized view +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +NOTICE: role "regress_ivm_admin" does not exist, skipping +DROP USER IF EXISTS regress_ivm_user; +NOTICE: role "regress_ivm_user" does not exist, skipping +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +NOTICE: could not create an index on materialized view "ivm_rls" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user +(1 row) + +RESET SESSION AUTHORIZATION; +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user + 3 | baz | regress_ivm_user +(2 rows) + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +-- +(1 row) + +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+-------+------------------ + 2 | bar | regress_ivm_user + 3 | baz | regress_ivm_user + 6 | corge | regress_ivm_user +(3 rows) + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +NOTICE: could not create an index on materialized view "ivm_rls2" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +RESET SESSION AUTHORIZATION; +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +-- +(1 row) + +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + id | data | owner | num +----+-------+------------------+--------- + 2 | bar | regress_ivm_user | two + 3 | baz_2 | regress_ivm_user | three_2 + 6 | corge | regress_ivm_user | six +(3 rows) + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +NOTICE: could not create an index on materialized view "mv_update_same" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + i +--- + 2 +(1 row) + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +NOTICE: created index "mv_self_ref_index" on materialized view "mv_self_ref" +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; + a | b +----+---- + 11 | + 12 | 11 + 13 | 12 +(3 rows) + +ROLLBACK; +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; +NOTICE: created index "mv_idx1_index" on materialized view "mv_idx1" +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; +NOTICE: created index "mv_idx2_index" on materialized view "mv_idx2" +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; +NOTICE: created index "mv_idx3_index" on materialized view "mv_idx3" +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +NOTICE: could not create an index on materialized view "mv_idx4" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; +NOTICE: could not create an index on materialized view "mv_idx5" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); +NOTICE: could not create an index on materialized view "mv_idx6" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ERROR: data type json has no default operator class for access method "btree" +ROLLBACK; +-- cleanup +DROP TABLE rls_tbl CASCADE; +NOTICE: drop cascades to 2 other objects +DETAIL: drop cascades to materialized view ivm_rls +drop cascades to materialized view ivm_rls2 +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; +DROP TABLE mv_base_b CASCADE; +NOTICE: drop cascades to 3 other objects +DETAIL: drop cascades to materialized view mv_ivm_1 +drop cascades to view b_view +drop cascades to materialized view b_mview +DROP TABLE mv_base_a CASCADE; diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index 8fa0a6c47fb..7caca5f64fd 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -77,6 +77,7 @@ test: brin_bloom brin_multi # Another group of parallel tests # ---------- test: create_table_like alter_generic alter_operator misc async dbsize merge misc_functions nls sysviews tsrf tid tidscan tidrangescan collate.utf8 collate.icu.utf8 incremental_sort create_role without_overlaps generated_virtual +test: incremental_matview # collate.linux.utf8 and collate.icu.utf8 tests cannot be run in parallel with each other # psql depends on create_am diff --git a/src/test/regress/sql/incremental_matview.sql b/src/test/regress/sql/incremental_matview.sql new file mode 100644 index 00000000000..2d55c393d6f --- /dev/null +++ b/src/test/regress/sql/incremental_matview.sql @@ -0,0 +1,580 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); + +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +REFRESH MATERIALIZED VIEW mv_ivm_1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; + +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; +ROLLBACK; + +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +DROP MATERIALIZED VIEW mv_ivm_rename; + +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +DROP MATERIALIZED VIEW mv_ivm_unique; + +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; + + +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +ROLLBACK; + +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +ROLLBACK; + +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +ROLLBACK; + +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +ROLLBACK; + +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +ROLLBACK; + +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min; + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); + +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; +ROLLBACK; + +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +SELECT * FROM mv_self ORDER BY v1; +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; +SELECT * FROM mv_self ORDER BY v1; + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + +ROLLBACK; + +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +SELECT * FROM mv ORDER BY v1; +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; +SELECT * FROM mv ORDER BY v1; +ROLLBACK; + +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +SELECT * FROM mv_ri ORDER BY i1; +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; +ROLLBACK; + +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +-- IMMV containing user defined type +BEGIN; + +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); + +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; + +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); + +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); + +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + +ROLLBACK; + +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; + +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; + +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; + +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; + +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; + +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); + +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; + +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); + +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ROLLBACK; + +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; + +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; + +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; + +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; + +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; + +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; + +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); + +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +DROP USER IF EXISTS regress_ivm_user; +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; + +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); + +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; + +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; + +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; +RESET SESSION AUTHORIZATION; + +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +RESET SESSION AUTHORIZATION; + +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; +ROLLBACK; + +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); + +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; + +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; + +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; + +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; + +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); + +ROLLBACK; + +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ROLLBACK; + +-- cleanup + +DROP TABLE rls_tbl CASCADE; +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; + +DROP TABLE mv_base_b CASCADE; +DROP TABLE mv_base_a CASCADE; -- 2.43.0 --Multipart=_Wed__1_Jul_2026_00_04_01_+0900_OVSy2WWK_9aByzDJ Content-Type: text/x-diff; name="v38-0009-Add-support-for-min-max-aggregates-for-IVM.patch" Content-Disposition: attachment; filename="v38-0009-Add-support-for-min-max-aggregates-for-IVM.patch" Content-Transfer-Encoding: 7bit ^ permalink raw reply [nested|flat] 78+ messages in thread
* [PATCH v39 7/8] Add regression tests for Incremental View Maintenance @ 2026-05-29 09:31 Yugo Nagata <[email protected]> 0 siblings, 0 replies; 78+ messages in thread From: Yugo Nagata @ 2026-05-29 09:31 UTC (permalink / raw) --- .../isolation/expected/ivm-create-insert.out | 285 ++++++++ .../isolation/expected/ivm-create-insert2.out | 305 ++++++++ .../isolation/expected/ivm-create-insert3.out | 305 ++++++++ .../isolation/expected/ivm-insert-insert.out | 497 +++++++++++++ .../isolation/expected/ivm-insert-insert2.out | 373 ++++++++++ .../isolation/expected/ivm-insert-insert3.out | 373 ++++++++++ .../isolation/expected/ivm-refresh-insert.out | 213 ++++++ .../expected/ivm-refresh-insert2.out | 191 +++++ .../expected/ivm-refresh-insert3.out | 191 +++++ src/test/isolation/isolation_schedule | 9 + .../isolation/specs/ivm-create-insert.spec | 47 ++ .../isolation/specs/ivm-create-insert2.spec | 54 ++ .../isolation/specs/ivm-create-insert3.spec | 54 ++ .../isolation/specs/ivm-insert-insert.spec | 62 ++ .../isolation/specs/ivm-insert-insert2.spec | 62 ++ .../isolation/specs/ivm-insert-insert3.spec | 62 ++ .../isolation/specs/ivm-refresh-insert.spec | 46 ++ .../isolation/specs/ivm-refresh-insert2.spec | 46 ++ .../isolation/specs/ivm-refresh-insert3.spec | 46 ++ .../regress/expected/incremental_matview.out | 667 ++++++++++++++++++ src/test/regress/parallel_schedule | 1 + src/test/regress/sql/incremental_matview.sql | 407 +++++++++++ 22 files changed, 4296 insertions(+) create mode 100644 src/test/isolation/expected/ivm-create-insert.out create mode 100644 src/test/isolation/expected/ivm-create-insert2.out create mode 100644 src/test/isolation/expected/ivm-create-insert3.out create mode 100644 src/test/isolation/expected/ivm-insert-insert.out create mode 100644 src/test/isolation/expected/ivm-insert-insert2.out create mode 100644 src/test/isolation/expected/ivm-insert-insert3.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert2.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert3.out create mode 100644 src/test/isolation/specs/ivm-create-insert.spec create mode 100644 src/test/isolation/specs/ivm-create-insert2.spec create mode 100644 src/test/isolation/specs/ivm-create-insert3.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert2.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert3.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert2.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert3.spec create mode 100644 src/test/regress/expected/incremental_matview.out create mode 100644 src/test/regress/sql/incremental_matview.sql diff --git a/src/test/isolation/expected/ivm-create-insert.out b/src/test/isolation/expected/ivm-create-insert.out new file mode 100644 index 00000000000..5da00043aba --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert.out @@ -0,0 +1,285 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-create-insert2.out b/src/test/isolation/expected/ivm-create-insert2.out new file mode 100644 index 00000000000..907d892c6d4 --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert2.out @@ -0,0 +1,305 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + diff --git a/src/test/isolation/expected/ivm-create-insert3.out b/src/test/isolation/expected/ivm-create-insert3.out new file mode 100644 index 00000000000..907d892c6d4 --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert3.out @@ -0,0 +1,305 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert.out b/src/test/isolation/expected/ivm-insert-insert.out new file mode 100644 index 00000000000..5ca4cfea677 --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert.out @@ -0,0 +1,497 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; <waiting ...> +step c1: COMMIT; +step update2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; <waiting ...> +step c1: COMMIT; +step update2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; <waiting ...> +step c2: COMMIT; +step update1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; <waiting ...> +step c2: COMMIT; +step update1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); <waiting ...> +step c1: COMMIT; +step insert2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); <waiting ...> +step c1: COMMIT; +step insert2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); <waiting ...> +step c2: COMMIT; +step insert1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); <waiting ...> +step c2: COMMIT; +step insert1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert2.out b/src/test/isolation/expected/ivm-insert-insert2.out new file mode 100644 index 00000000000..e1c66d4de5e --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert2.out @@ -0,0 +1,373 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert3.out b/src/test/isolation/expected/ivm-insert-insert3.out new file mode 100644 index 00000000000..e1c66d4de5e --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert3.out @@ -0,0 +1,373 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert.out b/src/test/isolation/expected/ivm-refresh-insert.out new file mode 100644 index 00000000000..a925938bf1c --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert.out @@ -0,0 +1,213 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert2.out b/src/test/isolation/expected/ivm-refresh-insert2.out new file mode 100644 index 00000000000..dc1b16ae34e --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert2.out @@ -0,0 +1,191 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert3.out b/src/test/isolation/expected/ivm-refresh-insert3.out new file mode 100644 index 00000000000..dc1b16ae34e --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert3.out @@ -0,0 +1,191 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/isolation_schedule b/src/test/isolation/isolation_schedule index b8ebe92553c..6b7e873b370 100644 --- a/src/test/isolation/isolation_schedule +++ b/src/test/isolation/isolation_schedule @@ -128,3 +128,12 @@ test: matview-write-skew test: lock-nowait test: for-portion-of test: ddl-dependency-locking +test: ivm-create-insert +test: ivm-create-insert2 +test: ivm-create-insert3 +test: ivm-insert-insert +test: ivm-insert-insert2 +test: ivm-insert-insert3 +test: ivm-refresh-insert +test: ivm-refresh-insert2 +test: ivm-refresh-insert3 diff --git a/src/test/isolation/specs/ivm-create-insert.spec b/src/test/isolation/specs/ivm-create-insert.spec new file mode 100644 index 00000000000..ccd6fd080a9 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert.spec @@ -0,0 +1,47 @@ +# Test interaction between concurrent transactions performing +# create and insert in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-create-insert2.spec b/src/test/isolation/specs/ivm-create-insert2.spec new file mode 100644 index 00000000000..02cec85ae07 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert2.spec @@ -0,0 +1,54 @@ +# Test interaction between concurrent transactions performing +# create and insert in REPEATABLE READ isolation level +# +# Note: +# In this isolation level, it is possible that create_immv could +# create an inconsistent view not including effects of a concurrent +# transaction. So, an warning message is raised to suggest using it +# in READ COMMITTED or executing refresh_immv to make sure to +# make the view contents consistent. + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-create-insert3.spec b/src/test/isolation/specs/ivm-create-insert3.spec new file mode 100644 index 00000000000..19ce03185a4 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert3.spec @@ -0,0 +1,54 @@ +# Test interaction between concurrent transactions performing +# create and insert in SERIALIZABLE isolation level +# +# Note: +# In this isolation level, it is possible that create_immv could +# create an inconsistent view not including effects of a concurrent +# transaction. So, an warning message is raised to suggest using it +# in READ COMMITTED or executing refresh_immv to make sure to +# make the view contents consistent. + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert.spec b/src/test/isolation/specs/ivm-insert-insert.spec new file mode 100644 index 00000000000..b8f794ca191 --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert2.spec b/src/test/isolation/specs/ivm-insert-insert2.spec new file mode 100644 index 00000000000..ed086d1ba1e --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert2.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in REPEATABLE READ isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert3.spec b/src/test/isolation/specs/ivm-insert-insert3.spec new file mode 100644 index 00000000000..b18bd121033 --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert3.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in SERIALIZABLE isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert.spec b/src/test/isolation/specs/ivm-refresh-insert.spec new file mode 100644 index 00000000000..d7181251962 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert2.spec b/src/test/isolation/specs/ivm-refresh-insert2.spec new file mode 100644 index 00000000000..f2d1d5013f2 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert2.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in REPEATABLE READ isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert3.spec b/src/test/isolation/specs/ivm-refresh-insert3.spec new file mode 100644 index 00000000000..0ec2b1d1de0 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert3.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in SERIALIZABLE isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/regress/expected/incremental_matview.out b/src/test/regress/expected/incremental_matview.out new file mode 100644 index 00000000000..c7fd19fdca3 --- /dev/null +++ b/src/test/regress/expected/incremental_matview.out @@ -0,0 +1,667 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ERROR: materialized view "mv_ivm_1" has not been populated +HINT: Use the REFRESH MATERIALIZED VIEW command. +REFRESH MATERIALIZED VIEW mv_ivm_1; +NOTICE: could not create an index on materialized view "mv_ivm_1" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 17 +(1 row) + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 1 +(1 row) + +ROLLBACK; +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- DISTINCT not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT * FROM mv_base_a; +ERROR: DISTINCT is not supported on incrementally maintainable materialized view +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +NOTICE: could not create an index on materialized view "mv_ivm_func" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +NOTICE: could not create an index on materialized view "mv_ivm_no_tbl" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- result of materialized view have duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_duplicate" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 20 + 30 + 40 + 50 +(6 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +ROLLBACK; +-- aggregate not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +ERROR: aggregate function is not supported on incrementally maintainable materialized view +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +NOTICE: could not create an index on materialized view "mv_self" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +----+---- + 10 | 10 + 20 | 20 + 30 | 30 +(3 rows) + +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 30 | 30 + 40 | 40 + 200 | 200 +(3 rows) + +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 130 | 130 + 300 | 300 +(4 rows) + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 70 | 70 + 70 | 77 + 77 | 70 + 77 | 77 + 130 | 130 + 300 | 300 +(8 rows) + +ROLLBACK; +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY v1; + v1 | v2 +----+----- + 10 | 100 + 20 | 200 + 30 | 300 +(3 rows) + +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv ORDER BY v1; + v1 | v2 +------+----- + 10 | 100 + 11 | 100 + 1020 | 200 + 1020 | 222 +(4 rows) + +ROLLBACK; +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +NOTICE: created index "mv_ri_index" on materialized view "mv_ri" +SELECT * FROM mv_ri ORDER BY i1; + i1 | i2 +----+---- + 1 | 1 + 2 | 2 + 3 | 3 +(3 rows) + +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; + i1 | i2 +----+---- + 3 | 3 + 10 | 10 +(2 rows) + +ROLLBACK; +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | +(2 rows) + +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | 20 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i +--- +(0 rows) + +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; + i +--- + 1 + +(2 rows) + +ROLLBACK; +-- IMMV containing user defined type +BEGIN; +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: return type mytype is only a shell +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: argument type mytype is only a shell +LINE 1: CREATE FUNCTION mytype_out(mytype) + ^ +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +NOTICE: could not create an index on materialized view "mv_mytype" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + x +--- + 1 +(1 row) + +ROLLBACK; +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +ERROR: OUTER JOIN is not supported on incrementally maintainable materialized view +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +ERROR: CTE is not supported on incrementally maintainable materialized view +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +ERROR: ORDER BY clause is not supported on incrementally maintainable materialized view +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; +ERROR: HAVING clause is not supported on incrementally maintainable materialized view +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; +ERROR: mutable function is not supported on incrementally maintainable materialized view +HINT: functions must be marked IMMUTABLE +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; +ERROR: LIMIT/OFFSET clause is not supported on incrementally maintainable materialized view +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; +ERROR: DISTINCT is not supported on incrementally maintainable materialized view +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); +ERROR: TABLESAMPLE clause is not supported on incrementally maintainable materialized view +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; +ERROR: window functions are not supported on incrementally maintainable materialized view +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ERROR: inheritance parent is not supported on incrementally maintainable materialized view +ROLLBACK; +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; +ERROR: UNION/INTERSECT/EXCEPT statements are not supported on incrementally maintainable materialized view +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; +ERROR: empty target list is not supported on incrementally maintainable materialized view +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; +ERROR: FOR UPDATE/SHARE clause is not supported on incrementally maintainable materialized view +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; +ERROR: column name __ivm_count__ is not supported on incrementally maintainable materialized view +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; +ERROR: aggregate function is not supported on incrementally maintainable materialized view +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); +ERROR: VALUES is not supported on incrementally maintainable materialized view +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +NOTICE: role "regress_ivm_admin" does not exist, skipping +DROP USER IF EXISTS regress_ivm_user; +NOTICE: role "regress_ivm_user" does not exist, skipping +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +NOTICE: could not create an index on materialized view "ivm_rls" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user +(1 row) + +RESET SESSION AUTHORIZATION; +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user + 3 | baz | regress_ivm_user +(2 rows) + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +-- +(1 row) + +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+-------+------------------ + 2 | bar | regress_ivm_user + 3 | baz | regress_ivm_user + 6 | corge | regress_ivm_user +(3 rows) + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +NOTICE: could not create an index on materialized view "ivm_rls2" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +RESET SESSION AUTHORIZATION; +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +-- +(1 row) + +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + id | data | owner | num +----+-------+------------------+--------- + 2 | bar | regress_ivm_user | two + 3 | baz_2 | regress_ivm_user | three_2 + 6 | corge | regress_ivm_user | six +(3 rows) + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +NOTICE: could not create an index on materialized view "mv_update_same" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + i +--- + 2 +(1 row) + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +NOTICE: created index "mv_self_ref_index" on materialized view "mv_self_ref" +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; + a | b +----+---- + 11 | + 12 | 11 + 13 | 12 +(3 rows) + +ROLLBACK; +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; +NOTICE: created index "mv_idx3_index" on materialized view "mv_idx3" +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +NOTICE: could not create an index on materialized view "mv_idx4" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; +NOTICE: could not create an index on materialized view "mv_idx5" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); +NOTICE: could not create an index on materialized view "mv_idx6" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ERROR: data type json has no default operator class for access method "btree" +ROLLBACK; +-- cleanup +DROP TABLE rls_tbl CASCADE; +NOTICE: drop cascades to 2 other objects +DETAIL: drop cascades to materialized view ivm_rls +drop cascades to materialized view ivm_rls2 +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; +DROP TABLE mv_base_b CASCADE; +NOTICE: drop cascades to 3 other objects +DETAIL: drop cascades to materialized view mv_ivm_1 +drop cascades to view b_view +drop cascades to materialized view b_mview +DROP TABLE mv_base_a CASCADE; diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index 8fa0a6c47fb..7caca5f64fd 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -77,6 +77,7 @@ test: brin_bloom brin_multi # Another group of parallel tests # ---------- test: create_table_like alter_generic alter_operator misc async dbsize merge misc_functions nls sysviews tsrf tid tidscan tidrangescan collate.utf8 collate.icu.utf8 incremental_sort create_role without_overlaps generated_virtual +test: incremental_matview # collate.linux.utf8 and collate.icu.utf8 tests cannot be run in parallel with each other # psql depends on create_am diff --git a/src/test/regress/sql/incremental_matview.sql b/src/test/regress/sql/incremental_matview.sql new file mode 100644 index 00000000000..7313ad82f3e --- /dev/null +++ b/src/test/regress/sql/incremental_matview.sql @@ -0,0 +1,407 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); + +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +REFRESH MATERIALIZED VIEW mv_ivm_1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; + +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; +ROLLBACK; + +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- DISTINCT not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT * FROM mv_base_a; + +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; + + +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +ROLLBACK; + +-- result of materialized view have duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +ROLLBACK; + +-- aggregate not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; + +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +SELECT * FROM mv_self ORDER BY v1; +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; +SELECT * FROM mv_self ORDER BY v1; + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + +ROLLBACK; + +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +SELECT * FROM mv ORDER BY v1; +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; +SELECT * FROM mv ORDER BY v1; +ROLLBACK; + +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +SELECT * FROM mv_ri ORDER BY i1; +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; +ROLLBACK; + +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +-- IMMV containing user defined type +BEGIN; + +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); + +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; + +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); + +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); + +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + +ROLLBACK; + +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; + +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; + +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; + +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; + +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; + +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); + +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; + +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ROLLBACK; + +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; + +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; + +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; + +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; + +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; + +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); + +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +DROP USER IF EXISTS regress_ivm_user; +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; + +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); + +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; + +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; + +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; +RESET SESSION AUTHORIZATION; + +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +RESET SESSION AUTHORIZATION; + +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; +ROLLBACK; + +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); + +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; + +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; + +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); + +ROLLBACK; + +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ROLLBACK; + +-- cleanup + +DROP TABLE rls_tbl CASCADE; +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; + +DROP TABLE mv_base_b CASCADE; +DROP TABLE mv_base_a CASCADE; -- 2.43.0 --Multipart=_Fri__3_Jul_2026_19_11_16_+0900_CskxSIu_iGcDMEyM Content-Type: text/x-diff; name="v39-0006-Add-Incremental-View-Maintenance-support.patch" Content-Disposition: attachment; filename="v39-0006-Add-Incremental-View-Maintenance-support.patch" Content-Transfer-Encoding: 7bit ^ permalink raw reply [nested|flat] 78+ messages in thread
* [PATCH v37 10/11] Add regression tests for Incremental View Maintenance @ 2026-05-29 09:31 Yugo Nagata <[email protected]> 0 siblings, 0 replies; 78+ messages in thread From: Yugo Nagata @ 2026-05-29 09:31 UTC (permalink / raw) --- src/test/isolation/isolation_schedule | 9 + .../regress/expected/incremental_matview.out | 1100 +++++++++++++++++ src/test/regress/parallel_schedule | 1 + src/test/regress/sql/incremental_matview.sql | 580 +++++++++ 4 files changed, 1690 insertions(+) create mode 100644 src/test/regress/expected/incremental_matview.out create mode 100644 src/test/regress/sql/incremental_matview.sql diff --git a/src/test/isolation/isolation_schedule b/src/test/isolation/isolation_schedule index 15c33fad4c5..111fd465207 100644 --- a/src/test/isolation/isolation_schedule +++ b/src/test/isolation/isolation_schedule @@ -127,3 +127,12 @@ test: matview-write-skew test: lock-nowait test: for-portion-of test: ddl-dependency-locking +test: ivm-create-insert +test: ivm-create-insert2 +test: ivm-create-insert3 +test: ivm-insert-insert +test: ivm-insert-insert2 +test: ivm-insert-insert3 +test: ivm-refresh-insert +test: ivm-refresh-insert2 +test: ivm-refresh-insert3 diff --git a/src/test/regress/expected/incremental_matview.out b/src/test/regress/expected/incremental_matview.out new file mode 100644 index 00000000000..f215aa88e48 --- /dev/null +++ b/src/test/regress/expected/incremental_matview.out @@ -0,0 +1,1100 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ERROR: materialized view "mv_ivm_1" has not been populated +HINT: Use the REFRESH MATERIALIZED VIEW command. +REFRESH MATERIALIZED VIEW mv_ivm_1; +NOTICE: could not create an index on materialized view "mv_ivm_1" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 17 +(1 row) + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 1 +(1 row) + +ROLLBACK; +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_rename_index" on materialized view "mv_ivm_rename" +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +ERROR: IVM column can not be renamed +DROP MATERIALIZED VIEW mv_ivm_rename; +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_unique_index" on materialized view "mv_ivm_unique" +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +ERROR: unique index creation on IVM columns is not supported +DROP MATERIALIZED VIEW mv_ivm_unique; +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +NOTICE: could not create an index on materialized view "mv_ivm_func" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +NOTICE: could not create an index on materialized view "mv_ivm_no_tbl" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_duplicate" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +NOTICE: created index "mv_ivm_distinct_index" on materialized view "mv_ivm_distinct" +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 20 + 30 + 40 + 50 +(6 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +ROLLBACK; +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 120 | 2 | 60.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+---------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 220 | 2 | 110.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 20 | 1 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 120 | 2 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; + sum | count +-----+------- +(0 rows) + +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; + i | sum | count +---+-----+------- +(0 rows) + +ROLLBACK; +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 150 | 5 | 30.0000000000000000 +(1 row) + +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 210 | 6 | 35.0000000000000000 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +NOTICE: created index "mv_ivm_avg_bug_index" on materialized view "mv_ivm_avg_bug" +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 3 | 3.3333333333333333 + 2 | 80 | 3 | 26.6666666666666667 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_min_max_index" on materialized view "mv_ivm_min_max" +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 10 + 2 | 20 | 20 + 3 | 30 | 30 + 4 | 40 | 40 + 5 | 50 | 50 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 12 + 2 | 20 | 22 + 3 | 30 | 32 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 11 | 12 + 2 | 20 | 22 + 3 | 30 | 31 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min_max" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 50 +(1 row) + +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 0 | 70 +(1 row) + +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 60 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + | +(1 row) + +ROLLBACK; +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min; + min +----- + 10 +(1 row) + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + min +----- + 20 +(1 row) + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; + min +----- + 30 +(1 row) + +ROLLBACK; +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | sum +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | b +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ERROR: too many column names were specified +ROLLBACK; +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +NOTICE: could not create an index on materialized view "mv_self" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +----+---- + 10 | 10 + 20 | 20 + 30 | 30 +(3 rows) + +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 30 | 30 + 40 | 40 + 200 | 200 +(3 rows) + +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 130 | 130 + 300 | 300 +(4 rows) + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 70 | 70 + 70 | 77 + 77 | 70 + 77 | 77 + 130 | 130 + 300 | 300 +(8 rows) + +ROLLBACK; +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY v1; + v1 | v2 +----+----- + 10 | 100 + 20 | 200 + 30 | 300 +(3 rows) + +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv ORDER BY v1; + v1 | v2 +------+----- + 10 | 100 + 11 | 100 + 1020 | 200 + 1020 | 222 +(4 rows) + +ROLLBACK; +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +NOTICE: created index "mv_ri_index" on materialized view "mv_ri" +SELECT * FROM mv_ri ORDER BY i1; + i1 | i2 +----+---- + 1 | 1 + 2 | 2 + 3 | 3 +(3 rows) + +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; + i1 | i2 +----+---- + 3 | 3 + 10 | 10 +(2 rows) + +ROLLBACK; +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | +(2 rows) + +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | 20 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i +--- +(0 rows) + +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; + i +--- + 1 + +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 30 + | 3 +(2 rows) + +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 300 + | 30 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 1 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 4 +(1 row) + +ROLLBACK; +-- IMMV containing user defined type +BEGIN; +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: return type mytype is only a shell +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: argument type mytype is only a shell +LINE 1: CREATE FUNCTION mytype_out(mytype) + ^ +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +NOTICE: could not create an index on materialized view "mv_mytype" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + x +--- + 1 +(1 row) + +ROLLBACK; +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +ERROR: OUTER JOIN is not supported on incrementally maintainable materialized view +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +ERROR: CTE is not supported on incrementally maintainable materialized view +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +ERROR: ORDER BY clause is not supported on incrementally maintainable materialized view +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; +ERROR: HAVING clause is not supported on incrementally maintainable materialized view +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; +ERROR: mutable function is not supported on incrementally maintainable materialized view +HINT: functions must be marked IMMUTABLE +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; +ERROR: LIMIT/OFFSET clause is not supported on incrementally maintainable materialized view +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; +ERROR: DISTINCT ON is not supported on incrementally maintainable materialized view +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); +ERROR: TABLESAMPLE clause is not supported on incrementally maintainable materialized view +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; +ERROR: window functions are not supported on incrementally maintainable materialized view +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +ERROR: aggregate function with FILTER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +ERROR: aggregate function with DISTINCT arguments is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +ERROR: aggregate function with ORDER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); +ERROR: GROUPING SETS, ROLLUP, or CUBE clauses is not supported on incrementally maintainable materialized view +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ERROR: inheritance parent is not supported on incrementally maintainable materialized view +ROLLBACK; +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; +ERROR: UNION/INTERSECT/EXCEPT statements are not supported on incrementally maintainable materialized view +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; +ERROR: empty target list is not supported on incrementally maintainable materialized view +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; +ERROR: FOR UPDATE/SHARE clause is not supported on incrementally maintainable materialized view +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; +ERROR: column name __ivm_count__ is not supported on incrementally maintainable materialized view +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; +ERROR: GROUP BY expression not appearing in select list is not supported on incrementally maintainable materialized view +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); +ERROR: VALUES is not supported on incrementally maintainable materialized view +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +NOTICE: role "regress_ivm_admin" does not exist, skipping +DROP USER IF EXISTS regress_ivm_user; +NOTICE: role "regress_ivm_user" does not exist, skipping +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +NOTICE: could not create an index on materialized view "ivm_rls" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user +(1 row) + +RESET SESSION AUTHORIZATION; +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user + 3 | baz | regress_ivm_user +(2 rows) + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +-- +(1 row) + +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+-------+------------------ + 2 | bar | regress_ivm_user + 3 | baz | regress_ivm_user + 6 | corge | regress_ivm_user +(3 rows) + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +NOTICE: could not create an index on materialized view "ivm_rls2" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +RESET SESSION AUTHORIZATION; +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +-- +(1 row) + +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + id | data | owner | num +----+-------+------------------+--------- + 2 | bar | regress_ivm_user | two + 3 | baz_2 | regress_ivm_user | three_2 + 6 | corge | regress_ivm_user | six +(3 rows) + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +NOTICE: could not create an index on materialized view "mv_update_same" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + i +--- + 2 +(1 row) + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +NOTICE: created index "mv_self_ref_index" on materialized view "mv_self_ref" +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; + a | b +----+---- + 11 | + 12 | 11 + 13 | 12 +(3 rows) + +ROLLBACK; +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; +NOTICE: created index "mv_idx1_index" on materialized view "mv_idx1" +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; +NOTICE: created index "mv_idx2_index" on materialized view "mv_idx2" +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; +NOTICE: created index "mv_idx3_index" on materialized view "mv_idx3" +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +NOTICE: could not create an index on materialized view "mv_idx4" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; +NOTICE: could not create an index on materialized view "mv_idx5" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); +NOTICE: could not create an index on materialized view "mv_idx6" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ERROR: data type json has no default operator class for access method "btree" +ROLLBACK; +-- cleanup +DROP TABLE rls_tbl CASCADE; +NOTICE: drop cascades to 2 other objects +DETAIL: drop cascades to materialized view ivm_rls +drop cascades to materialized view ivm_rls2 +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; +DROP TABLE mv_base_b CASCADE; +NOTICE: drop cascades to 3 other objects +DETAIL: drop cascades to materialized view mv_ivm_1 +drop cascades to view b_view +drop cascades to materialized view b_mview +DROP TABLE mv_base_a CASCADE; diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index 8fa0a6c47fb..7caca5f64fd 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -77,6 +77,7 @@ test: brin_bloom brin_multi # Another group of parallel tests # ---------- test: create_table_like alter_generic alter_operator misc async dbsize merge misc_functions nls sysviews tsrf tid tidscan tidrangescan collate.utf8 collate.icu.utf8 incremental_sort create_role without_overlaps generated_virtual +test: incremental_matview # collate.linux.utf8 and collate.icu.utf8 tests cannot be run in parallel with each other # psql depends on create_am diff --git a/src/test/regress/sql/incremental_matview.sql b/src/test/regress/sql/incremental_matview.sql new file mode 100644 index 00000000000..2d55c393d6f --- /dev/null +++ b/src/test/regress/sql/incremental_matview.sql @@ -0,0 +1,580 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); + +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +REFRESH MATERIALIZED VIEW mv_ivm_1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; + +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; +ROLLBACK; + +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +DROP MATERIALIZED VIEW mv_ivm_rename; + +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +DROP MATERIALIZED VIEW mv_ivm_unique; + +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; + + +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +ROLLBACK; + +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +ROLLBACK; + +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +ROLLBACK; + +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +ROLLBACK; + +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +ROLLBACK; + +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min; + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); + +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; +ROLLBACK; + +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +SELECT * FROM mv_self ORDER BY v1; +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; +SELECT * FROM mv_self ORDER BY v1; + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + +ROLLBACK; + +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +SELECT * FROM mv ORDER BY v1; +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; +SELECT * FROM mv ORDER BY v1; +ROLLBACK; + +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +SELECT * FROM mv_ri ORDER BY i1; +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; +ROLLBACK; + +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +-- IMMV containing user defined type +BEGIN; + +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); + +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; + +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); + +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); + +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + +ROLLBACK; + +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; + +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; + +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; + +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; + +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; + +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); + +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; + +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); + +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ROLLBACK; + +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; + +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; + +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; + +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; + +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; + +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; + +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); + +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +DROP USER IF EXISTS regress_ivm_user; +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; + +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); + +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; + +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; + +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; +RESET SESSION AUTHORIZATION; + +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +RESET SESSION AUTHORIZATION; + +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; +ROLLBACK; + +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); + +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; + +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; + +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; + +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; + +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); + +ROLLBACK; + +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ROLLBACK; + +-- cleanup + +DROP TABLE rls_tbl CASCADE; +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; + +DROP TABLE mv_base_b CASCADE; +DROP TABLE mv_base_a CASCADE; -- 2.43.0 --Multipart=_Fri__29_May_2026_23_14_17_+0900_Te0o73X2VqYK57Gd Content-Type: text/x-diff; name="v37-0009-Add-support-for-min-max-aggregates-for-IVM.patch" Content-Disposition: attachment; filename="v37-0009-Add-support-for-min-max-aggregates-for-IVM.patch" Content-Transfer-Encoding: 7bit ^ permalink raw reply [nested|flat] 78+ messages in thread
* [PATCH v39 7/8] Add regression tests for Incremental View Maintenance @ 2026-05-29 09:31 Yugo Nagata <[email protected]> 0 siblings, 0 replies; 78+ messages in thread From: Yugo Nagata @ 2026-05-29 09:31 UTC (permalink / raw) --- .../isolation/expected/ivm-create-insert.out | 285 ++++++++ .../isolation/expected/ivm-create-insert2.out | 305 ++++++++ .../isolation/expected/ivm-create-insert3.out | 305 ++++++++ .../isolation/expected/ivm-insert-insert.out | 497 +++++++++++++ .../isolation/expected/ivm-insert-insert2.out | 373 ++++++++++ .../isolation/expected/ivm-insert-insert3.out | 373 ++++++++++ .../isolation/expected/ivm-refresh-insert.out | 213 ++++++ .../expected/ivm-refresh-insert2.out | 191 +++++ .../expected/ivm-refresh-insert3.out | 191 +++++ src/test/isolation/isolation_schedule | 9 + .../isolation/specs/ivm-create-insert.spec | 47 ++ .../isolation/specs/ivm-create-insert2.spec | 54 ++ .../isolation/specs/ivm-create-insert3.spec | 54 ++ .../isolation/specs/ivm-insert-insert.spec | 62 ++ .../isolation/specs/ivm-insert-insert2.spec | 62 ++ .../isolation/specs/ivm-insert-insert3.spec | 62 ++ .../isolation/specs/ivm-refresh-insert.spec | 46 ++ .../isolation/specs/ivm-refresh-insert2.spec | 46 ++ .../isolation/specs/ivm-refresh-insert3.spec | 46 ++ .../regress/expected/incremental_matview.out | 667 ++++++++++++++++++ src/test/regress/parallel_schedule | 1 + src/test/regress/sql/incremental_matview.sql | 407 +++++++++++ 22 files changed, 4296 insertions(+) create mode 100644 src/test/isolation/expected/ivm-create-insert.out create mode 100644 src/test/isolation/expected/ivm-create-insert2.out create mode 100644 src/test/isolation/expected/ivm-create-insert3.out create mode 100644 src/test/isolation/expected/ivm-insert-insert.out create mode 100644 src/test/isolation/expected/ivm-insert-insert2.out create mode 100644 src/test/isolation/expected/ivm-insert-insert3.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert2.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert3.out create mode 100644 src/test/isolation/specs/ivm-create-insert.spec create mode 100644 src/test/isolation/specs/ivm-create-insert2.spec create mode 100644 src/test/isolation/specs/ivm-create-insert3.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert2.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert3.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert2.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert3.spec create mode 100644 src/test/regress/expected/incremental_matview.out create mode 100644 src/test/regress/sql/incremental_matview.sql diff --git a/src/test/isolation/expected/ivm-create-insert.out b/src/test/isolation/expected/ivm-create-insert.out new file mode 100644 index 00000000000..5da00043aba --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert.out @@ -0,0 +1,285 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-create-insert2.out b/src/test/isolation/expected/ivm-create-insert2.out new file mode 100644 index 00000000000..907d892c6d4 --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert2.out @@ -0,0 +1,305 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + diff --git a/src/test/isolation/expected/ivm-create-insert3.out b/src/test/isolation/expected/ivm-create-insert3.out new file mode 100644 index 00000000000..907d892c6d4 --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert3.out @@ -0,0 +1,305 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert.out b/src/test/isolation/expected/ivm-insert-insert.out new file mode 100644 index 00000000000..5ca4cfea677 --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert.out @@ -0,0 +1,497 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; <waiting ...> +step c1: COMMIT; +step update2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; <waiting ...> +step c1: COMMIT; +step update2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; <waiting ...> +step c2: COMMIT; +step update1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; <waiting ...> +step c2: COMMIT; +step update1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); <waiting ...> +step c1: COMMIT; +step insert2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); <waiting ...> +step c1: COMMIT; +step insert2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); <waiting ...> +step c2: COMMIT; +step insert1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); <waiting ...> +step c2: COMMIT; +step insert1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert2.out b/src/test/isolation/expected/ivm-insert-insert2.out new file mode 100644 index 00000000000..e1c66d4de5e --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert2.out @@ -0,0 +1,373 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert3.out b/src/test/isolation/expected/ivm-insert-insert3.out new file mode 100644 index 00000000000..e1c66d4de5e --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert3.out @@ -0,0 +1,373 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert.out b/src/test/isolation/expected/ivm-refresh-insert.out new file mode 100644 index 00000000000..a925938bf1c --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert.out @@ -0,0 +1,213 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert2.out b/src/test/isolation/expected/ivm-refresh-insert2.out new file mode 100644 index 00000000000..dc1b16ae34e --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert2.out @@ -0,0 +1,191 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert3.out b/src/test/isolation/expected/ivm-refresh-insert3.out new file mode 100644 index 00000000000..dc1b16ae34e --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert3.out @@ -0,0 +1,191 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/isolation_schedule b/src/test/isolation/isolation_schedule index b8ebe92553c..6b7e873b370 100644 --- a/src/test/isolation/isolation_schedule +++ b/src/test/isolation/isolation_schedule @@ -128,3 +128,12 @@ test: matview-write-skew test: lock-nowait test: for-portion-of test: ddl-dependency-locking +test: ivm-create-insert +test: ivm-create-insert2 +test: ivm-create-insert3 +test: ivm-insert-insert +test: ivm-insert-insert2 +test: ivm-insert-insert3 +test: ivm-refresh-insert +test: ivm-refresh-insert2 +test: ivm-refresh-insert3 diff --git a/src/test/isolation/specs/ivm-create-insert.spec b/src/test/isolation/specs/ivm-create-insert.spec new file mode 100644 index 00000000000..ccd6fd080a9 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert.spec @@ -0,0 +1,47 @@ +# Test interaction between concurrent transactions performing +# create and insert in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-create-insert2.spec b/src/test/isolation/specs/ivm-create-insert2.spec new file mode 100644 index 00000000000..02cec85ae07 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert2.spec @@ -0,0 +1,54 @@ +# Test interaction between concurrent transactions performing +# create and insert in REPEATABLE READ isolation level +# +# Note: +# In this isolation level, it is possible that create_immv could +# create an inconsistent view not including effects of a concurrent +# transaction. So, an warning message is raised to suggest using it +# in READ COMMITTED or executing refresh_immv to make sure to +# make the view contents consistent. + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-create-insert3.spec b/src/test/isolation/specs/ivm-create-insert3.spec new file mode 100644 index 00000000000..19ce03185a4 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert3.spec @@ -0,0 +1,54 @@ +# Test interaction between concurrent transactions performing +# create and insert in SERIALIZABLE isolation level +# +# Note: +# In this isolation level, it is possible that create_immv could +# create an inconsistent view not including effects of a concurrent +# transaction. So, an warning message is raised to suggest using it +# in READ COMMITTED or executing refresh_immv to make sure to +# make the view contents consistent. + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert.spec b/src/test/isolation/specs/ivm-insert-insert.spec new file mode 100644 index 00000000000..b8f794ca191 --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert2.spec b/src/test/isolation/specs/ivm-insert-insert2.spec new file mode 100644 index 00000000000..ed086d1ba1e --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert2.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in REPEATABLE READ isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert3.spec b/src/test/isolation/specs/ivm-insert-insert3.spec new file mode 100644 index 00000000000..b18bd121033 --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert3.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in SERIALIZABLE isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert.spec b/src/test/isolation/specs/ivm-refresh-insert.spec new file mode 100644 index 00000000000..d7181251962 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert2.spec b/src/test/isolation/specs/ivm-refresh-insert2.spec new file mode 100644 index 00000000000..f2d1d5013f2 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert2.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in REPEATABLE READ isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert3.spec b/src/test/isolation/specs/ivm-refresh-insert3.spec new file mode 100644 index 00000000000..0ec2b1d1de0 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert3.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in SERIALIZABLE isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/regress/expected/incremental_matview.out b/src/test/regress/expected/incremental_matview.out new file mode 100644 index 00000000000..c7fd19fdca3 --- /dev/null +++ b/src/test/regress/expected/incremental_matview.out @@ -0,0 +1,667 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ERROR: materialized view "mv_ivm_1" has not been populated +HINT: Use the REFRESH MATERIALIZED VIEW command. +REFRESH MATERIALIZED VIEW mv_ivm_1; +NOTICE: could not create an index on materialized view "mv_ivm_1" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 17 +(1 row) + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 1 +(1 row) + +ROLLBACK; +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- DISTINCT not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT * FROM mv_base_a; +ERROR: DISTINCT is not supported on incrementally maintainable materialized view +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +NOTICE: could not create an index on materialized view "mv_ivm_func" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +NOTICE: could not create an index on materialized view "mv_ivm_no_tbl" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- result of materialized view have duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_duplicate" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 20 + 30 + 40 + 50 +(6 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +ROLLBACK; +-- aggregate not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +ERROR: aggregate function is not supported on incrementally maintainable materialized view +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +NOTICE: could not create an index on materialized view "mv_self" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +----+---- + 10 | 10 + 20 | 20 + 30 | 30 +(3 rows) + +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 30 | 30 + 40 | 40 + 200 | 200 +(3 rows) + +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 130 | 130 + 300 | 300 +(4 rows) + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 70 | 70 + 70 | 77 + 77 | 70 + 77 | 77 + 130 | 130 + 300 | 300 +(8 rows) + +ROLLBACK; +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY v1; + v1 | v2 +----+----- + 10 | 100 + 20 | 200 + 30 | 300 +(3 rows) + +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv ORDER BY v1; + v1 | v2 +------+----- + 10 | 100 + 11 | 100 + 1020 | 200 + 1020 | 222 +(4 rows) + +ROLLBACK; +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +NOTICE: created index "mv_ri_index" on materialized view "mv_ri" +SELECT * FROM mv_ri ORDER BY i1; + i1 | i2 +----+---- + 1 | 1 + 2 | 2 + 3 | 3 +(3 rows) + +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; + i1 | i2 +----+---- + 3 | 3 + 10 | 10 +(2 rows) + +ROLLBACK; +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | +(2 rows) + +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | 20 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i +--- +(0 rows) + +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; + i +--- + 1 + +(2 rows) + +ROLLBACK; +-- IMMV containing user defined type +BEGIN; +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: return type mytype is only a shell +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: argument type mytype is only a shell +LINE 1: CREATE FUNCTION mytype_out(mytype) + ^ +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +NOTICE: could not create an index on materialized view "mv_mytype" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + x +--- + 1 +(1 row) + +ROLLBACK; +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +ERROR: OUTER JOIN is not supported on incrementally maintainable materialized view +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +ERROR: CTE is not supported on incrementally maintainable materialized view +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +ERROR: ORDER BY clause is not supported on incrementally maintainable materialized view +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; +ERROR: HAVING clause is not supported on incrementally maintainable materialized view +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; +ERROR: mutable function is not supported on incrementally maintainable materialized view +HINT: functions must be marked IMMUTABLE +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; +ERROR: LIMIT/OFFSET clause is not supported on incrementally maintainable materialized view +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; +ERROR: DISTINCT is not supported on incrementally maintainable materialized view +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); +ERROR: TABLESAMPLE clause is not supported on incrementally maintainable materialized view +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; +ERROR: window functions are not supported on incrementally maintainable materialized view +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ERROR: inheritance parent is not supported on incrementally maintainable materialized view +ROLLBACK; +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; +ERROR: UNION/INTERSECT/EXCEPT statements are not supported on incrementally maintainable materialized view +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; +ERROR: empty target list is not supported on incrementally maintainable materialized view +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; +ERROR: FOR UPDATE/SHARE clause is not supported on incrementally maintainable materialized view +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; +ERROR: column name __ivm_count__ is not supported on incrementally maintainable materialized view +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; +ERROR: aggregate function is not supported on incrementally maintainable materialized view +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); +ERROR: VALUES is not supported on incrementally maintainable materialized view +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +NOTICE: role "regress_ivm_admin" does not exist, skipping +DROP USER IF EXISTS regress_ivm_user; +NOTICE: role "regress_ivm_user" does not exist, skipping +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +NOTICE: could not create an index on materialized view "ivm_rls" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user +(1 row) + +RESET SESSION AUTHORIZATION; +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user + 3 | baz | regress_ivm_user +(2 rows) + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +-- +(1 row) + +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+-------+------------------ + 2 | bar | regress_ivm_user + 3 | baz | regress_ivm_user + 6 | corge | regress_ivm_user +(3 rows) + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +NOTICE: could not create an index on materialized view "ivm_rls2" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +RESET SESSION AUTHORIZATION; +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +-- +(1 row) + +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + id | data | owner | num +----+-------+------------------+--------- + 2 | bar | regress_ivm_user | two + 3 | baz_2 | regress_ivm_user | three_2 + 6 | corge | regress_ivm_user | six +(3 rows) + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +NOTICE: could not create an index on materialized view "mv_update_same" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + i +--- + 2 +(1 row) + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +NOTICE: created index "mv_self_ref_index" on materialized view "mv_self_ref" +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; + a | b +----+---- + 11 | + 12 | 11 + 13 | 12 +(3 rows) + +ROLLBACK; +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; +NOTICE: created index "mv_idx3_index" on materialized view "mv_idx3" +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +NOTICE: could not create an index on materialized view "mv_idx4" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; +NOTICE: could not create an index on materialized view "mv_idx5" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); +NOTICE: could not create an index on materialized view "mv_idx6" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ERROR: data type json has no default operator class for access method "btree" +ROLLBACK; +-- cleanup +DROP TABLE rls_tbl CASCADE; +NOTICE: drop cascades to 2 other objects +DETAIL: drop cascades to materialized view ivm_rls +drop cascades to materialized view ivm_rls2 +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; +DROP TABLE mv_base_b CASCADE; +NOTICE: drop cascades to 3 other objects +DETAIL: drop cascades to materialized view mv_ivm_1 +drop cascades to view b_view +drop cascades to materialized view b_mview +DROP TABLE mv_base_a CASCADE; diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index 8fa0a6c47fb..7caca5f64fd 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -77,6 +77,7 @@ test: brin_bloom brin_multi # Another group of parallel tests # ---------- test: create_table_like alter_generic alter_operator misc async dbsize merge misc_functions nls sysviews tsrf tid tidscan tidrangescan collate.utf8 collate.icu.utf8 incremental_sort create_role without_overlaps generated_virtual +test: incremental_matview # collate.linux.utf8 and collate.icu.utf8 tests cannot be run in parallel with each other # psql depends on create_am diff --git a/src/test/regress/sql/incremental_matview.sql b/src/test/regress/sql/incremental_matview.sql new file mode 100644 index 00000000000..7313ad82f3e --- /dev/null +++ b/src/test/regress/sql/incremental_matview.sql @@ -0,0 +1,407 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); + +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +REFRESH MATERIALIZED VIEW mv_ivm_1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; + +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; +ROLLBACK; + +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- DISTINCT not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT * FROM mv_base_a; + +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; + + +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +ROLLBACK; + +-- result of materialized view have duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +ROLLBACK; + +-- aggregate not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; + +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +SELECT * FROM mv_self ORDER BY v1; +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; +SELECT * FROM mv_self ORDER BY v1; + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + +ROLLBACK; + +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +SELECT * FROM mv ORDER BY v1; +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; +SELECT * FROM mv ORDER BY v1; +ROLLBACK; + +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +SELECT * FROM mv_ri ORDER BY i1; +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; +ROLLBACK; + +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +-- IMMV containing user defined type +BEGIN; + +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); + +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; + +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); + +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); + +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + +ROLLBACK; + +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; + +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; + +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; + +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; + +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; + +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); + +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; + +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ROLLBACK; + +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; + +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; + +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; + +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; + +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; + +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); + +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +DROP USER IF EXISTS regress_ivm_user; +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; + +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); + +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; + +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; + +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; +RESET SESSION AUTHORIZATION; + +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +RESET SESSION AUTHORIZATION; + +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; +ROLLBACK; + +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); + +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; + +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; + +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); + +ROLLBACK; + +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ROLLBACK; + +-- cleanup + +DROP TABLE rls_tbl CASCADE; +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; + +DROP TABLE mv_base_b CASCADE; +DROP TABLE mv_base_a CASCADE; -- 2.43.0 --Multipart=_Fri__3_Jul_2026_19_11_16_+0900_CskxSIu_iGcDMEyM Content-Type: text/x-diff; name="v39-0006-Add-Incremental-View-Maintenance-support.patch" Content-Disposition: attachment; filename="v39-0006-Add-Incremental-View-Maintenance-support.patch" Content-Transfer-Encoding: 7bit ^ permalink raw reply [nested|flat] 78+ messages in thread
* [PATCH v37 10/11] Add regression tests for Incremental View Maintenance @ 2026-05-29 09:31 Yugo Nagata <[email protected]> 0 siblings, 0 replies; 78+ messages in thread From: Yugo Nagata @ 2026-05-29 09:31 UTC (permalink / raw) --- src/test/isolation/isolation_schedule | 9 + .../regress/expected/incremental_matview.out | 1100 +++++++++++++++++ src/test/regress/parallel_schedule | 1 + src/test/regress/sql/incremental_matview.sql | 580 +++++++++ 4 files changed, 1690 insertions(+) create mode 100644 src/test/regress/expected/incremental_matview.out create mode 100644 src/test/regress/sql/incremental_matview.sql diff --git a/src/test/isolation/isolation_schedule b/src/test/isolation/isolation_schedule index 15c33fad4c5..111fd465207 100644 --- a/src/test/isolation/isolation_schedule +++ b/src/test/isolation/isolation_schedule @@ -127,3 +127,12 @@ test: matview-write-skew test: lock-nowait test: for-portion-of test: ddl-dependency-locking +test: ivm-create-insert +test: ivm-create-insert2 +test: ivm-create-insert3 +test: ivm-insert-insert +test: ivm-insert-insert2 +test: ivm-insert-insert3 +test: ivm-refresh-insert +test: ivm-refresh-insert2 +test: ivm-refresh-insert3 diff --git a/src/test/regress/expected/incremental_matview.out b/src/test/regress/expected/incremental_matview.out new file mode 100644 index 00000000000..f215aa88e48 --- /dev/null +++ b/src/test/regress/expected/incremental_matview.out @@ -0,0 +1,1100 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ERROR: materialized view "mv_ivm_1" has not been populated +HINT: Use the REFRESH MATERIALIZED VIEW command. +REFRESH MATERIALIZED VIEW mv_ivm_1; +NOTICE: could not create an index on materialized view "mv_ivm_1" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 17 +(1 row) + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 1 +(1 row) + +ROLLBACK; +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_rename_index" on materialized view "mv_ivm_rename" +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +ERROR: IVM column can not be renamed +DROP MATERIALIZED VIEW mv_ivm_rename; +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_unique_index" on materialized view "mv_ivm_unique" +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +ERROR: unique index creation on IVM columns is not supported +DROP MATERIALIZED VIEW mv_ivm_unique; +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +NOTICE: could not create an index on materialized view "mv_ivm_func" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +NOTICE: could not create an index on materialized view "mv_ivm_no_tbl" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_duplicate" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +NOTICE: created index "mv_ivm_distinct_index" on materialized view "mv_ivm_distinct" +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 20 + 30 + 40 + 50 +(6 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +ROLLBACK; +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 120 | 2 | 60.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+---------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 220 | 2 | 110.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 20 | 1 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 120 | 2 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; + sum | count +-----+------- +(0 rows) + +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; + i | sum | count +---+-----+------- +(0 rows) + +ROLLBACK; +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 150 | 5 | 30.0000000000000000 +(1 row) + +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 210 | 6 | 35.0000000000000000 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +NOTICE: created index "mv_ivm_avg_bug_index" on materialized view "mv_ivm_avg_bug" +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 3 | 3.3333333333333333 + 2 | 80 | 3 | 26.6666666666666667 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_min_max_index" on materialized view "mv_ivm_min_max" +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 10 + 2 | 20 | 20 + 3 | 30 | 30 + 4 | 40 | 40 + 5 | 50 | 50 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 12 + 2 | 20 | 22 + 3 | 30 | 32 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 11 | 12 + 2 | 20 | 22 + 3 | 30 | 31 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min_max" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 50 +(1 row) + +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 0 | 70 +(1 row) + +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 60 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + | +(1 row) + +ROLLBACK; +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min; + min +----- + 10 +(1 row) + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + min +----- + 20 +(1 row) + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; + min +----- + 30 +(1 row) + +ROLLBACK; +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | sum +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | b +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ERROR: too many column names were specified +ROLLBACK; +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +NOTICE: could not create an index on materialized view "mv_self" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +----+---- + 10 | 10 + 20 | 20 + 30 | 30 +(3 rows) + +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 30 | 30 + 40 | 40 + 200 | 200 +(3 rows) + +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 130 | 130 + 300 | 300 +(4 rows) + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 70 | 70 + 70 | 77 + 77 | 70 + 77 | 77 + 130 | 130 + 300 | 300 +(8 rows) + +ROLLBACK; +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY v1; + v1 | v2 +----+----- + 10 | 100 + 20 | 200 + 30 | 300 +(3 rows) + +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv ORDER BY v1; + v1 | v2 +------+----- + 10 | 100 + 11 | 100 + 1020 | 200 + 1020 | 222 +(4 rows) + +ROLLBACK; +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +NOTICE: created index "mv_ri_index" on materialized view "mv_ri" +SELECT * FROM mv_ri ORDER BY i1; + i1 | i2 +----+---- + 1 | 1 + 2 | 2 + 3 | 3 +(3 rows) + +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; + i1 | i2 +----+---- + 3 | 3 + 10 | 10 +(2 rows) + +ROLLBACK; +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | +(2 rows) + +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | 20 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i +--- +(0 rows) + +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; + i +--- + 1 + +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 30 + | 3 +(2 rows) + +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 300 + | 30 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 1 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 4 +(1 row) + +ROLLBACK; +-- IMMV containing user defined type +BEGIN; +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: return type mytype is only a shell +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: argument type mytype is only a shell +LINE 1: CREATE FUNCTION mytype_out(mytype) + ^ +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +NOTICE: could not create an index on materialized view "mv_mytype" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + x +--- + 1 +(1 row) + +ROLLBACK; +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +ERROR: OUTER JOIN is not supported on incrementally maintainable materialized view +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +ERROR: CTE is not supported on incrementally maintainable materialized view +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +ERROR: ORDER BY clause is not supported on incrementally maintainable materialized view +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; +ERROR: HAVING clause is not supported on incrementally maintainable materialized view +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; +ERROR: mutable function is not supported on incrementally maintainable materialized view +HINT: functions must be marked IMMUTABLE +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; +ERROR: LIMIT/OFFSET clause is not supported on incrementally maintainable materialized view +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; +ERROR: DISTINCT ON is not supported on incrementally maintainable materialized view +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); +ERROR: TABLESAMPLE clause is not supported on incrementally maintainable materialized view +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; +ERROR: window functions are not supported on incrementally maintainable materialized view +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +ERROR: aggregate function with FILTER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +ERROR: aggregate function with DISTINCT arguments is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +ERROR: aggregate function with ORDER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); +ERROR: GROUPING SETS, ROLLUP, or CUBE clauses is not supported on incrementally maintainable materialized view +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ERROR: inheritance parent is not supported on incrementally maintainable materialized view +ROLLBACK; +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; +ERROR: UNION/INTERSECT/EXCEPT statements are not supported on incrementally maintainable materialized view +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; +ERROR: empty target list is not supported on incrementally maintainable materialized view +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; +ERROR: FOR UPDATE/SHARE clause is not supported on incrementally maintainable materialized view +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; +ERROR: column name __ivm_count__ is not supported on incrementally maintainable materialized view +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; +ERROR: GROUP BY expression not appearing in select list is not supported on incrementally maintainable materialized view +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); +ERROR: VALUES is not supported on incrementally maintainable materialized view +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +NOTICE: role "regress_ivm_admin" does not exist, skipping +DROP USER IF EXISTS regress_ivm_user; +NOTICE: role "regress_ivm_user" does not exist, skipping +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +NOTICE: could not create an index on materialized view "ivm_rls" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user +(1 row) + +RESET SESSION AUTHORIZATION; +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user + 3 | baz | regress_ivm_user +(2 rows) + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +-- +(1 row) + +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+-------+------------------ + 2 | bar | regress_ivm_user + 3 | baz | regress_ivm_user + 6 | corge | regress_ivm_user +(3 rows) + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +NOTICE: could not create an index on materialized view "ivm_rls2" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +RESET SESSION AUTHORIZATION; +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +-- +(1 row) + +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + id | data | owner | num +----+-------+------------------+--------- + 2 | bar | regress_ivm_user | two + 3 | baz_2 | regress_ivm_user | three_2 + 6 | corge | regress_ivm_user | six +(3 rows) + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +NOTICE: could not create an index on materialized view "mv_update_same" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + i +--- + 2 +(1 row) + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +NOTICE: created index "mv_self_ref_index" on materialized view "mv_self_ref" +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; + a | b +----+---- + 11 | + 12 | 11 + 13 | 12 +(3 rows) + +ROLLBACK; +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; +NOTICE: created index "mv_idx1_index" on materialized view "mv_idx1" +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; +NOTICE: created index "mv_idx2_index" on materialized view "mv_idx2" +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; +NOTICE: created index "mv_idx3_index" on materialized view "mv_idx3" +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +NOTICE: could not create an index on materialized view "mv_idx4" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; +NOTICE: could not create an index on materialized view "mv_idx5" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); +NOTICE: could not create an index on materialized view "mv_idx6" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ERROR: data type json has no default operator class for access method "btree" +ROLLBACK; +-- cleanup +DROP TABLE rls_tbl CASCADE; +NOTICE: drop cascades to 2 other objects +DETAIL: drop cascades to materialized view ivm_rls +drop cascades to materialized view ivm_rls2 +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; +DROP TABLE mv_base_b CASCADE; +NOTICE: drop cascades to 3 other objects +DETAIL: drop cascades to materialized view mv_ivm_1 +drop cascades to view b_view +drop cascades to materialized view b_mview +DROP TABLE mv_base_a CASCADE; diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index 8fa0a6c47fb..7caca5f64fd 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -77,6 +77,7 @@ test: brin_bloom brin_multi # Another group of parallel tests # ---------- test: create_table_like alter_generic alter_operator misc async dbsize merge misc_functions nls sysviews tsrf tid tidscan tidrangescan collate.utf8 collate.icu.utf8 incremental_sort create_role without_overlaps generated_virtual +test: incremental_matview # collate.linux.utf8 and collate.icu.utf8 tests cannot be run in parallel with each other # psql depends on create_am diff --git a/src/test/regress/sql/incremental_matview.sql b/src/test/regress/sql/incremental_matview.sql new file mode 100644 index 00000000000..2d55c393d6f --- /dev/null +++ b/src/test/regress/sql/incremental_matview.sql @@ -0,0 +1,580 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); + +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +REFRESH MATERIALIZED VIEW mv_ivm_1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; + +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; +ROLLBACK; + +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +DROP MATERIALIZED VIEW mv_ivm_rename; + +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +DROP MATERIALIZED VIEW mv_ivm_unique; + +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; + + +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +ROLLBACK; + +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +ROLLBACK; + +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +ROLLBACK; + +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +ROLLBACK; + +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +ROLLBACK; + +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min; + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); + +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; +ROLLBACK; + +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +SELECT * FROM mv_self ORDER BY v1; +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; +SELECT * FROM mv_self ORDER BY v1; + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + +ROLLBACK; + +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +SELECT * FROM mv ORDER BY v1; +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; +SELECT * FROM mv ORDER BY v1; +ROLLBACK; + +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +SELECT * FROM mv_ri ORDER BY i1; +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; +ROLLBACK; + +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +-- IMMV containing user defined type +BEGIN; + +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); + +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; + +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); + +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); + +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + +ROLLBACK; + +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; + +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; + +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; + +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; + +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; + +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); + +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; + +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); + +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ROLLBACK; + +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; + +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; + +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; + +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; + +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; + +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; + +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); + +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +DROP USER IF EXISTS regress_ivm_user; +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; + +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); + +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; + +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; + +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; +RESET SESSION AUTHORIZATION; + +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +RESET SESSION AUTHORIZATION; + +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; +ROLLBACK; + +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); + +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; + +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; + +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; + +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; + +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); + +ROLLBACK; + +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ROLLBACK; + +-- cleanup + +DROP TABLE rls_tbl CASCADE; +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; + +DROP TABLE mv_base_b CASCADE; +DROP TABLE mv_base_a CASCADE; -- 2.43.0 --Multipart=_Fri__29_May_2026_23_14_17_+0900_Te0o73X2VqYK57Gd Content-Type: text/x-diff; name="v37-0009-Add-support-for-min-max-aggregates-for-IVM.patch" Content-Disposition: attachment; filename="v37-0009-Add-support-for-min-max-aggregates-for-IVM.patch" Content-Transfer-Encoding: 7bit ^ permalink raw reply [nested|flat] 78+ messages in thread
* [PATCH v38 10/11] Add regression tests for Incremental View Maintenance @ 2026-05-29 09:31 Yugo Nagata <[email protected]> 0 siblings, 0 replies; 78+ messages in thread From: Yugo Nagata @ 2026-05-29 09:31 UTC (permalink / raw) --- .../isolation/expected/ivm-create-insert.out | 285 +++++ .../isolation/expected/ivm-create-insert2.out | 305 +++++ .../isolation/expected/ivm-create-insert3.out | 305 +++++ .../isolation/expected/ivm-insert-insert.out | 497 ++++++++ .../isolation/expected/ivm-insert-insert2.out | 373 ++++++ .../isolation/expected/ivm-insert-insert3.out | 373 ++++++ .../isolation/expected/ivm-refresh-insert.out | 213 ++++ .../expected/ivm-refresh-insert2.out | 191 +++ .../expected/ivm-refresh-insert3.out | 191 +++ src/test/isolation/isolation_schedule | 9 + .../isolation/specs/ivm-create-insert.spec | 47 + .../isolation/specs/ivm-create-insert2.spec | 54 + .../isolation/specs/ivm-create-insert3.spec | 54 + .../isolation/specs/ivm-insert-insert.spec | 62 + .../isolation/specs/ivm-insert-insert2.spec | 62 + .../isolation/specs/ivm-insert-insert3.spec | 62 + .../isolation/specs/ivm-refresh-insert.spec | 46 + .../isolation/specs/ivm-refresh-insert2.spec | 46 + .../isolation/specs/ivm-refresh-insert3.spec | 46 + .../regress/expected/incremental_matview.out | 1100 +++++++++++++++++ src/test/regress/parallel_schedule | 1 + src/test/regress/sql/incremental_matview.sql | 580 +++++++++ 22 files changed, 4902 insertions(+) create mode 100644 src/test/isolation/expected/ivm-create-insert.out create mode 100644 src/test/isolation/expected/ivm-create-insert2.out create mode 100644 src/test/isolation/expected/ivm-create-insert3.out create mode 100644 src/test/isolation/expected/ivm-insert-insert.out create mode 100644 src/test/isolation/expected/ivm-insert-insert2.out create mode 100644 src/test/isolation/expected/ivm-insert-insert3.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert2.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert3.out create mode 100644 src/test/isolation/specs/ivm-create-insert.spec create mode 100644 src/test/isolation/specs/ivm-create-insert2.spec create mode 100644 src/test/isolation/specs/ivm-create-insert3.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert2.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert3.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert2.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert3.spec create mode 100644 src/test/regress/expected/incremental_matview.out create mode 100644 src/test/regress/sql/incremental_matview.sql diff --git a/src/test/isolation/expected/ivm-create-insert.out b/src/test/isolation/expected/ivm-create-insert.out new file mode 100644 index 00000000000..5da00043aba --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert.out @@ -0,0 +1,285 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-create-insert2.out b/src/test/isolation/expected/ivm-create-insert2.out new file mode 100644 index 00000000000..907d892c6d4 --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert2.out @@ -0,0 +1,305 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + diff --git a/src/test/isolation/expected/ivm-create-insert3.out b/src/test/isolation/expected/ivm-create-insert3.out new file mode 100644 index 00000000000..907d892c6d4 --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert3.out @@ -0,0 +1,305 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert.out b/src/test/isolation/expected/ivm-insert-insert.out new file mode 100644 index 00000000000..5ca4cfea677 --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert.out @@ -0,0 +1,497 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; <waiting ...> +step c1: COMMIT; +step update2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; <waiting ...> +step c1: COMMIT; +step update2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; <waiting ...> +step c2: COMMIT; +step update1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; <waiting ...> +step c2: COMMIT; +step update1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); <waiting ...> +step c1: COMMIT; +step insert2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); <waiting ...> +step c1: COMMIT; +step insert2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); <waiting ...> +step c2: COMMIT; +step insert1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); <waiting ...> +step c2: COMMIT; +step insert1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert2.out b/src/test/isolation/expected/ivm-insert-insert2.out new file mode 100644 index 00000000000..e1c66d4de5e --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert2.out @@ -0,0 +1,373 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert3.out b/src/test/isolation/expected/ivm-insert-insert3.out new file mode 100644 index 00000000000..e1c66d4de5e --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert3.out @@ -0,0 +1,373 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert.out b/src/test/isolation/expected/ivm-refresh-insert.out new file mode 100644 index 00000000000..a925938bf1c --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert.out @@ -0,0 +1,213 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert2.out b/src/test/isolation/expected/ivm-refresh-insert2.out new file mode 100644 index 00000000000..dc1b16ae34e --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert2.out @@ -0,0 +1,191 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert3.out b/src/test/isolation/expected/ivm-refresh-insert3.out new file mode 100644 index 00000000000..dc1b16ae34e --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert3.out @@ -0,0 +1,191 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/isolation_schedule b/src/test/isolation/isolation_schedule index b8ebe92553c..6b7e873b370 100644 --- a/src/test/isolation/isolation_schedule +++ b/src/test/isolation/isolation_schedule @@ -128,3 +128,12 @@ test: matview-write-skew test: lock-nowait test: for-portion-of test: ddl-dependency-locking +test: ivm-create-insert +test: ivm-create-insert2 +test: ivm-create-insert3 +test: ivm-insert-insert +test: ivm-insert-insert2 +test: ivm-insert-insert3 +test: ivm-refresh-insert +test: ivm-refresh-insert2 +test: ivm-refresh-insert3 diff --git a/src/test/isolation/specs/ivm-create-insert.spec b/src/test/isolation/specs/ivm-create-insert.spec new file mode 100644 index 00000000000..ccd6fd080a9 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert.spec @@ -0,0 +1,47 @@ +# Test interaction between concurrent transactions performing +# create and insert in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-create-insert2.spec b/src/test/isolation/specs/ivm-create-insert2.spec new file mode 100644 index 00000000000..02cec85ae07 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert2.spec @@ -0,0 +1,54 @@ +# Test interaction between concurrent transactions performing +# create and insert in REPEATABLE READ isolation level +# +# Note: +# In this isolation level, it is possible that create_immv could +# create an inconsistent view not including effects of a concurrent +# transaction. So, an warning message is raised to suggest using it +# in READ COMMITTED or executing refresh_immv to make sure to +# make the view contents consistent. + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-create-insert3.spec b/src/test/isolation/specs/ivm-create-insert3.spec new file mode 100644 index 00000000000..19ce03185a4 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert3.spec @@ -0,0 +1,54 @@ +# Test interaction between concurrent transactions performing +# create and insert in SERIALIZABLE isolation level +# +# Note: +# In this isolation level, it is possible that create_immv could +# create an inconsistent view not including effects of a concurrent +# transaction. So, an warning message is raised to suggest using it +# in READ COMMITTED or executing refresh_immv to make sure to +# make the view contents consistent. + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert.spec b/src/test/isolation/specs/ivm-insert-insert.spec new file mode 100644 index 00000000000..b8f794ca191 --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert2.spec b/src/test/isolation/specs/ivm-insert-insert2.spec new file mode 100644 index 00000000000..ed086d1ba1e --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert2.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in REPEATABLE READ isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert3.spec b/src/test/isolation/specs/ivm-insert-insert3.spec new file mode 100644 index 00000000000..b18bd121033 --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert3.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in SERIALIZABLE isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert.spec b/src/test/isolation/specs/ivm-refresh-insert.spec new file mode 100644 index 00000000000..d7181251962 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert2.spec b/src/test/isolation/specs/ivm-refresh-insert2.spec new file mode 100644 index 00000000000..f2d1d5013f2 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert2.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in REPEATABLE READ isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert3.spec b/src/test/isolation/specs/ivm-refresh-insert3.spec new file mode 100644 index 00000000000..0ec2b1d1de0 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert3.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in SERIALIZABLE isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/regress/expected/incremental_matview.out b/src/test/regress/expected/incremental_matview.out new file mode 100644 index 00000000000..f215aa88e48 --- /dev/null +++ b/src/test/regress/expected/incremental_matview.out @@ -0,0 +1,1100 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ERROR: materialized view "mv_ivm_1" has not been populated +HINT: Use the REFRESH MATERIALIZED VIEW command. +REFRESH MATERIALIZED VIEW mv_ivm_1; +NOTICE: could not create an index on materialized view "mv_ivm_1" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 17 +(1 row) + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 1 +(1 row) + +ROLLBACK; +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_rename_index" on materialized view "mv_ivm_rename" +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +ERROR: IVM column can not be renamed +DROP MATERIALIZED VIEW mv_ivm_rename; +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_unique_index" on materialized view "mv_ivm_unique" +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +ERROR: unique index creation on IVM columns is not supported +DROP MATERIALIZED VIEW mv_ivm_unique; +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +NOTICE: could not create an index on materialized view "mv_ivm_func" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +NOTICE: could not create an index on materialized view "mv_ivm_no_tbl" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_duplicate" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +NOTICE: created index "mv_ivm_distinct_index" on materialized view "mv_ivm_distinct" +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 20 + 30 + 40 + 50 +(6 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +ROLLBACK; +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 120 | 2 | 60.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+---------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 220 | 2 | 110.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 20 | 1 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 120 | 2 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; + sum | count +-----+------- +(0 rows) + +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; + i | sum | count +---+-----+------- +(0 rows) + +ROLLBACK; +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 150 | 5 | 30.0000000000000000 +(1 row) + +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 210 | 6 | 35.0000000000000000 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +NOTICE: created index "mv_ivm_avg_bug_index" on materialized view "mv_ivm_avg_bug" +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 3 | 3.3333333333333333 + 2 | 80 | 3 | 26.6666666666666667 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_min_max_index" on materialized view "mv_ivm_min_max" +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 10 + 2 | 20 | 20 + 3 | 30 | 30 + 4 | 40 | 40 + 5 | 50 | 50 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 12 + 2 | 20 | 22 + 3 | 30 | 32 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 11 | 12 + 2 | 20 | 22 + 3 | 30 | 31 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min_max" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 50 +(1 row) + +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 0 | 70 +(1 row) + +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 60 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + | +(1 row) + +ROLLBACK; +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min; + min +----- + 10 +(1 row) + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + min +----- + 20 +(1 row) + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; + min +----- + 30 +(1 row) + +ROLLBACK; +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | sum +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | b +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ERROR: too many column names were specified +ROLLBACK; +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +NOTICE: could not create an index on materialized view "mv_self" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +----+---- + 10 | 10 + 20 | 20 + 30 | 30 +(3 rows) + +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 30 | 30 + 40 | 40 + 200 | 200 +(3 rows) + +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 130 | 130 + 300 | 300 +(4 rows) + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 70 | 70 + 70 | 77 + 77 | 70 + 77 | 77 + 130 | 130 + 300 | 300 +(8 rows) + +ROLLBACK; +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY v1; + v1 | v2 +----+----- + 10 | 100 + 20 | 200 + 30 | 300 +(3 rows) + +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv ORDER BY v1; + v1 | v2 +------+----- + 10 | 100 + 11 | 100 + 1020 | 200 + 1020 | 222 +(4 rows) + +ROLLBACK; +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +NOTICE: created index "mv_ri_index" on materialized view "mv_ri" +SELECT * FROM mv_ri ORDER BY i1; + i1 | i2 +----+---- + 1 | 1 + 2 | 2 + 3 | 3 +(3 rows) + +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; + i1 | i2 +----+---- + 3 | 3 + 10 | 10 +(2 rows) + +ROLLBACK; +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | +(2 rows) + +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | 20 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i +--- +(0 rows) + +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; + i +--- + 1 + +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 30 + | 3 +(2 rows) + +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 300 + | 30 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 1 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 4 +(1 row) + +ROLLBACK; +-- IMMV containing user defined type +BEGIN; +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: return type mytype is only a shell +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: argument type mytype is only a shell +LINE 1: CREATE FUNCTION mytype_out(mytype) + ^ +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +NOTICE: could not create an index on materialized view "mv_mytype" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + x +--- + 1 +(1 row) + +ROLLBACK; +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +ERROR: OUTER JOIN is not supported on incrementally maintainable materialized view +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +ERROR: CTE is not supported on incrementally maintainable materialized view +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +ERROR: ORDER BY clause is not supported on incrementally maintainable materialized view +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; +ERROR: HAVING clause is not supported on incrementally maintainable materialized view +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; +ERROR: mutable function is not supported on incrementally maintainable materialized view +HINT: functions must be marked IMMUTABLE +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; +ERROR: LIMIT/OFFSET clause is not supported on incrementally maintainable materialized view +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; +ERROR: DISTINCT ON is not supported on incrementally maintainable materialized view +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); +ERROR: TABLESAMPLE clause is not supported on incrementally maintainable materialized view +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; +ERROR: window functions are not supported on incrementally maintainable materialized view +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +ERROR: aggregate function with FILTER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +ERROR: aggregate function with DISTINCT arguments is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +ERROR: aggregate function with ORDER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); +ERROR: GROUPING SETS, ROLLUP, or CUBE clauses is not supported on incrementally maintainable materialized view +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ERROR: inheritance parent is not supported on incrementally maintainable materialized view +ROLLBACK; +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; +ERROR: UNION/INTERSECT/EXCEPT statements are not supported on incrementally maintainable materialized view +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; +ERROR: empty target list is not supported on incrementally maintainable materialized view +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; +ERROR: FOR UPDATE/SHARE clause is not supported on incrementally maintainable materialized view +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; +ERROR: column name __ivm_count__ is not supported on incrementally maintainable materialized view +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; +ERROR: GROUP BY expression not appearing in select list is not supported on incrementally maintainable materialized view +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); +ERROR: VALUES is not supported on incrementally maintainable materialized view +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +NOTICE: role "regress_ivm_admin" does not exist, skipping +DROP USER IF EXISTS regress_ivm_user; +NOTICE: role "regress_ivm_user" does not exist, skipping +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +NOTICE: could not create an index on materialized view "ivm_rls" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user +(1 row) + +RESET SESSION AUTHORIZATION; +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user + 3 | baz | regress_ivm_user +(2 rows) + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +-- +(1 row) + +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+-------+------------------ + 2 | bar | regress_ivm_user + 3 | baz | regress_ivm_user + 6 | corge | regress_ivm_user +(3 rows) + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +NOTICE: could not create an index on materialized view "ivm_rls2" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +RESET SESSION AUTHORIZATION; +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +-- +(1 row) + +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + id | data | owner | num +----+-------+------------------+--------- + 2 | bar | regress_ivm_user | two + 3 | baz_2 | regress_ivm_user | three_2 + 6 | corge | regress_ivm_user | six +(3 rows) + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +NOTICE: could not create an index on materialized view "mv_update_same" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + i +--- + 2 +(1 row) + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +NOTICE: created index "mv_self_ref_index" on materialized view "mv_self_ref" +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; + a | b +----+---- + 11 | + 12 | 11 + 13 | 12 +(3 rows) + +ROLLBACK; +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; +NOTICE: created index "mv_idx1_index" on materialized view "mv_idx1" +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; +NOTICE: created index "mv_idx2_index" on materialized view "mv_idx2" +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; +NOTICE: created index "mv_idx3_index" on materialized view "mv_idx3" +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +NOTICE: could not create an index on materialized view "mv_idx4" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; +NOTICE: could not create an index on materialized view "mv_idx5" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); +NOTICE: could not create an index on materialized view "mv_idx6" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ERROR: data type json has no default operator class for access method "btree" +ROLLBACK; +-- cleanup +DROP TABLE rls_tbl CASCADE; +NOTICE: drop cascades to 2 other objects +DETAIL: drop cascades to materialized view ivm_rls +drop cascades to materialized view ivm_rls2 +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; +DROP TABLE mv_base_b CASCADE; +NOTICE: drop cascades to 3 other objects +DETAIL: drop cascades to materialized view mv_ivm_1 +drop cascades to view b_view +drop cascades to materialized view b_mview +DROP TABLE mv_base_a CASCADE; diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index 8fa0a6c47fb..7caca5f64fd 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -77,6 +77,7 @@ test: brin_bloom brin_multi # Another group of parallel tests # ---------- test: create_table_like alter_generic alter_operator misc async dbsize merge misc_functions nls sysviews tsrf tid tidscan tidrangescan collate.utf8 collate.icu.utf8 incremental_sort create_role without_overlaps generated_virtual +test: incremental_matview # collate.linux.utf8 and collate.icu.utf8 tests cannot be run in parallel with each other # psql depends on create_am diff --git a/src/test/regress/sql/incremental_matview.sql b/src/test/regress/sql/incremental_matview.sql new file mode 100644 index 00000000000..2d55c393d6f --- /dev/null +++ b/src/test/regress/sql/incremental_matview.sql @@ -0,0 +1,580 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); + +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +REFRESH MATERIALIZED VIEW mv_ivm_1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; + +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; +ROLLBACK; + +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +DROP MATERIALIZED VIEW mv_ivm_rename; + +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +DROP MATERIALIZED VIEW mv_ivm_unique; + +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; + + +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +ROLLBACK; + +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +ROLLBACK; + +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +ROLLBACK; + +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +ROLLBACK; + +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +ROLLBACK; + +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min; + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); + +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; +ROLLBACK; + +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +SELECT * FROM mv_self ORDER BY v1; +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; +SELECT * FROM mv_self ORDER BY v1; + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + +ROLLBACK; + +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +SELECT * FROM mv ORDER BY v1; +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; +SELECT * FROM mv ORDER BY v1; +ROLLBACK; + +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +SELECT * FROM mv_ri ORDER BY i1; +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; +ROLLBACK; + +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +-- IMMV containing user defined type +BEGIN; + +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); + +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; + +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); + +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); + +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + +ROLLBACK; + +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; + +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; + +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; + +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; + +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; + +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); + +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; + +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); + +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ROLLBACK; + +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; + +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; + +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; + +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; + +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; + +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; + +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); + +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +DROP USER IF EXISTS regress_ivm_user; +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; + +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); + +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; + +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; + +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; +RESET SESSION AUTHORIZATION; + +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +RESET SESSION AUTHORIZATION; + +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; +ROLLBACK; + +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); + +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; + +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; + +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; + +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; + +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); + +ROLLBACK; + +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ROLLBACK; + +-- cleanup + +DROP TABLE rls_tbl CASCADE; +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; + +DROP TABLE mv_base_b CASCADE; +DROP TABLE mv_base_a CASCADE; -- 2.43.0 --Multipart=_Wed__1_Jul_2026_00_04_01_+0900_OVSy2WWK_9aByzDJ Content-Type: text/x-diff; name="v38-0009-Add-support-for-min-max-aggregates-for-IVM.patch" Content-Disposition: attachment; filename="v38-0009-Add-support-for-min-max-aggregates-for-IVM.patch" Content-Transfer-Encoding: 7bit ^ permalink raw reply [nested|flat] 78+ messages in thread
* [PATCH v37 10/11] Add regression tests for Incremental View Maintenance @ 2026-05-29 09:31 Yugo Nagata <[email protected]> 0 siblings, 0 replies; 78+ messages in thread From: Yugo Nagata @ 2026-05-29 09:31 UTC (permalink / raw) --- src/test/isolation/isolation_schedule | 9 + .../regress/expected/incremental_matview.out | 1100 +++++++++++++++++ src/test/regress/parallel_schedule | 1 + src/test/regress/sql/incremental_matview.sql | 580 +++++++++ 4 files changed, 1690 insertions(+) create mode 100644 src/test/regress/expected/incremental_matview.out create mode 100644 src/test/regress/sql/incremental_matview.sql diff --git a/src/test/isolation/isolation_schedule b/src/test/isolation/isolation_schedule index 15c33fad4c5..111fd465207 100644 --- a/src/test/isolation/isolation_schedule +++ b/src/test/isolation/isolation_schedule @@ -127,3 +127,12 @@ test: matview-write-skew test: lock-nowait test: for-portion-of test: ddl-dependency-locking +test: ivm-create-insert +test: ivm-create-insert2 +test: ivm-create-insert3 +test: ivm-insert-insert +test: ivm-insert-insert2 +test: ivm-insert-insert3 +test: ivm-refresh-insert +test: ivm-refresh-insert2 +test: ivm-refresh-insert3 diff --git a/src/test/regress/expected/incremental_matview.out b/src/test/regress/expected/incremental_matview.out new file mode 100644 index 00000000000..f215aa88e48 --- /dev/null +++ b/src/test/regress/expected/incremental_matview.out @@ -0,0 +1,1100 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ERROR: materialized view "mv_ivm_1" has not been populated +HINT: Use the REFRESH MATERIALIZED VIEW command. +REFRESH MATERIALIZED VIEW mv_ivm_1; +NOTICE: could not create an index on materialized view "mv_ivm_1" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 17 +(1 row) + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 1 +(1 row) + +ROLLBACK; +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_rename_index" on materialized view "mv_ivm_rename" +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +ERROR: IVM column can not be renamed +DROP MATERIALIZED VIEW mv_ivm_rename; +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_unique_index" on materialized view "mv_ivm_unique" +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +ERROR: unique index creation on IVM columns is not supported +DROP MATERIALIZED VIEW mv_ivm_unique; +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +NOTICE: could not create an index on materialized view "mv_ivm_func" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +NOTICE: could not create an index on materialized view "mv_ivm_no_tbl" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_duplicate" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +NOTICE: created index "mv_ivm_distinct_index" on materialized view "mv_ivm_distinct" +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 20 + 30 + 40 + 50 +(6 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +ROLLBACK; +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 120 | 2 | 60.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+---------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 220 | 2 | 110.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 20 | 1 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 120 | 2 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; + sum | count +-----+------- +(0 rows) + +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; + i | sum | count +---+-----+------- +(0 rows) + +ROLLBACK; +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 150 | 5 | 30.0000000000000000 +(1 row) + +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 210 | 6 | 35.0000000000000000 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +NOTICE: created index "mv_ivm_avg_bug_index" on materialized view "mv_ivm_avg_bug" +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 3 | 3.3333333333333333 + 2 | 80 | 3 | 26.6666666666666667 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_min_max_index" on materialized view "mv_ivm_min_max" +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 10 + 2 | 20 | 20 + 3 | 30 | 30 + 4 | 40 | 40 + 5 | 50 | 50 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 12 + 2 | 20 | 22 + 3 | 30 | 32 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 11 | 12 + 2 | 20 | 22 + 3 | 30 | 31 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min_max" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 50 +(1 row) + +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 0 | 70 +(1 row) + +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 60 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + | +(1 row) + +ROLLBACK; +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min; + min +----- + 10 +(1 row) + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + min +----- + 20 +(1 row) + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; + min +----- + 30 +(1 row) + +ROLLBACK; +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | sum +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | b +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ERROR: too many column names were specified +ROLLBACK; +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +NOTICE: could not create an index on materialized view "mv_self" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +----+---- + 10 | 10 + 20 | 20 + 30 | 30 +(3 rows) + +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 30 | 30 + 40 | 40 + 200 | 200 +(3 rows) + +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 130 | 130 + 300 | 300 +(4 rows) + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 70 | 70 + 70 | 77 + 77 | 70 + 77 | 77 + 130 | 130 + 300 | 300 +(8 rows) + +ROLLBACK; +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY v1; + v1 | v2 +----+----- + 10 | 100 + 20 | 200 + 30 | 300 +(3 rows) + +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv ORDER BY v1; + v1 | v2 +------+----- + 10 | 100 + 11 | 100 + 1020 | 200 + 1020 | 222 +(4 rows) + +ROLLBACK; +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +NOTICE: created index "mv_ri_index" on materialized view "mv_ri" +SELECT * FROM mv_ri ORDER BY i1; + i1 | i2 +----+---- + 1 | 1 + 2 | 2 + 3 | 3 +(3 rows) + +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; + i1 | i2 +----+---- + 3 | 3 + 10 | 10 +(2 rows) + +ROLLBACK; +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | +(2 rows) + +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | 20 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i +--- +(0 rows) + +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; + i +--- + 1 + +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 30 + | 3 +(2 rows) + +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 300 + | 30 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 1 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 4 +(1 row) + +ROLLBACK; +-- IMMV containing user defined type +BEGIN; +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: return type mytype is only a shell +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: argument type mytype is only a shell +LINE 1: CREATE FUNCTION mytype_out(mytype) + ^ +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +NOTICE: could not create an index on materialized view "mv_mytype" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + x +--- + 1 +(1 row) + +ROLLBACK; +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +ERROR: OUTER JOIN is not supported on incrementally maintainable materialized view +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +ERROR: CTE is not supported on incrementally maintainable materialized view +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +ERROR: ORDER BY clause is not supported on incrementally maintainable materialized view +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; +ERROR: HAVING clause is not supported on incrementally maintainable materialized view +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; +ERROR: mutable function is not supported on incrementally maintainable materialized view +HINT: functions must be marked IMMUTABLE +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; +ERROR: LIMIT/OFFSET clause is not supported on incrementally maintainable materialized view +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; +ERROR: DISTINCT ON is not supported on incrementally maintainable materialized view +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); +ERROR: TABLESAMPLE clause is not supported on incrementally maintainable materialized view +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; +ERROR: window functions are not supported on incrementally maintainable materialized view +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +ERROR: aggregate function with FILTER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +ERROR: aggregate function with DISTINCT arguments is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +ERROR: aggregate function with ORDER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); +ERROR: GROUPING SETS, ROLLUP, or CUBE clauses is not supported on incrementally maintainable materialized view +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ERROR: inheritance parent is not supported on incrementally maintainable materialized view +ROLLBACK; +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; +ERROR: UNION/INTERSECT/EXCEPT statements are not supported on incrementally maintainable materialized view +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; +ERROR: empty target list is not supported on incrementally maintainable materialized view +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; +ERROR: FOR UPDATE/SHARE clause is not supported on incrementally maintainable materialized view +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; +ERROR: column name __ivm_count__ is not supported on incrementally maintainable materialized view +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; +ERROR: GROUP BY expression not appearing in select list is not supported on incrementally maintainable materialized view +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); +ERROR: VALUES is not supported on incrementally maintainable materialized view +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +NOTICE: role "regress_ivm_admin" does not exist, skipping +DROP USER IF EXISTS regress_ivm_user; +NOTICE: role "regress_ivm_user" does not exist, skipping +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +NOTICE: could not create an index on materialized view "ivm_rls" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user +(1 row) + +RESET SESSION AUTHORIZATION; +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user + 3 | baz | regress_ivm_user +(2 rows) + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +-- +(1 row) + +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+-------+------------------ + 2 | bar | regress_ivm_user + 3 | baz | regress_ivm_user + 6 | corge | regress_ivm_user +(3 rows) + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +NOTICE: could not create an index on materialized view "ivm_rls2" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +RESET SESSION AUTHORIZATION; +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +-- +(1 row) + +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + id | data | owner | num +----+-------+------------------+--------- + 2 | bar | regress_ivm_user | two + 3 | baz_2 | regress_ivm_user | three_2 + 6 | corge | regress_ivm_user | six +(3 rows) + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +NOTICE: could not create an index on materialized view "mv_update_same" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + i +--- + 2 +(1 row) + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +NOTICE: created index "mv_self_ref_index" on materialized view "mv_self_ref" +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; + a | b +----+---- + 11 | + 12 | 11 + 13 | 12 +(3 rows) + +ROLLBACK; +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; +NOTICE: created index "mv_idx1_index" on materialized view "mv_idx1" +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; +NOTICE: created index "mv_idx2_index" on materialized view "mv_idx2" +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; +NOTICE: created index "mv_idx3_index" on materialized view "mv_idx3" +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +NOTICE: could not create an index on materialized view "mv_idx4" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; +NOTICE: could not create an index on materialized view "mv_idx5" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); +NOTICE: could not create an index on materialized view "mv_idx6" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ERROR: data type json has no default operator class for access method "btree" +ROLLBACK; +-- cleanup +DROP TABLE rls_tbl CASCADE; +NOTICE: drop cascades to 2 other objects +DETAIL: drop cascades to materialized view ivm_rls +drop cascades to materialized view ivm_rls2 +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; +DROP TABLE mv_base_b CASCADE; +NOTICE: drop cascades to 3 other objects +DETAIL: drop cascades to materialized view mv_ivm_1 +drop cascades to view b_view +drop cascades to materialized view b_mview +DROP TABLE mv_base_a CASCADE; diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index 8fa0a6c47fb..7caca5f64fd 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -77,6 +77,7 @@ test: brin_bloom brin_multi # Another group of parallel tests # ---------- test: create_table_like alter_generic alter_operator misc async dbsize merge misc_functions nls sysviews tsrf tid tidscan tidrangescan collate.utf8 collate.icu.utf8 incremental_sort create_role without_overlaps generated_virtual +test: incremental_matview # collate.linux.utf8 and collate.icu.utf8 tests cannot be run in parallel with each other # psql depends on create_am diff --git a/src/test/regress/sql/incremental_matview.sql b/src/test/regress/sql/incremental_matview.sql new file mode 100644 index 00000000000..2d55c393d6f --- /dev/null +++ b/src/test/regress/sql/incremental_matview.sql @@ -0,0 +1,580 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); + +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +REFRESH MATERIALIZED VIEW mv_ivm_1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; + +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; +ROLLBACK; + +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +DROP MATERIALIZED VIEW mv_ivm_rename; + +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +DROP MATERIALIZED VIEW mv_ivm_unique; + +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; + + +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +ROLLBACK; + +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +ROLLBACK; + +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +ROLLBACK; + +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +ROLLBACK; + +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +ROLLBACK; + +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min; + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); + +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; +ROLLBACK; + +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +SELECT * FROM mv_self ORDER BY v1; +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; +SELECT * FROM mv_self ORDER BY v1; + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + +ROLLBACK; + +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +SELECT * FROM mv ORDER BY v1; +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; +SELECT * FROM mv ORDER BY v1; +ROLLBACK; + +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +SELECT * FROM mv_ri ORDER BY i1; +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; +ROLLBACK; + +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +-- IMMV containing user defined type +BEGIN; + +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); + +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; + +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); + +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); + +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + +ROLLBACK; + +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; + +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; + +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; + +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; + +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; + +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); + +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; + +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); + +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ROLLBACK; + +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; + +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; + +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; + +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; + +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; + +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; + +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); + +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +DROP USER IF EXISTS regress_ivm_user; +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; + +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); + +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; + +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; + +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; +RESET SESSION AUTHORIZATION; + +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +RESET SESSION AUTHORIZATION; + +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; +ROLLBACK; + +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); + +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; + +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; + +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; + +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; + +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); + +ROLLBACK; + +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ROLLBACK; + +-- cleanup + +DROP TABLE rls_tbl CASCADE; +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; + +DROP TABLE mv_base_b CASCADE; +DROP TABLE mv_base_a CASCADE; -- 2.43.0 --Multipart=_Fri__29_May_2026_23_14_17_+0900_Te0o73X2VqYK57Gd Content-Type: text/x-diff; name="v37-0009-Add-support-for-min-max-aggregates-for-IVM.patch" Content-Disposition: attachment; filename="v37-0009-Add-support-for-min-max-aggregates-for-IVM.patch" Content-Transfer-Encoding: 7bit ^ permalink raw reply [nested|flat] 78+ messages in thread
* [PATCH v37 10/11] Add regression tests for Incremental View Maintenance @ 2026-05-29 09:31 Yugo Nagata <[email protected]> 0 siblings, 0 replies; 78+ messages in thread From: Yugo Nagata @ 2026-05-29 09:31 UTC (permalink / raw) --- src/test/isolation/isolation_schedule | 9 + .../regress/expected/incremental_matview.out | 1100 +++++++++++++++++ src/test/regress/parallel_schedule | 1 + src/test/regress/sql/incremental_matview.sql | 580 +++++++++ 4 files changed, 1690 insertions(+) create mode 100644 src/test/regress/expected/incremental_matview.out create mode 100644 src/test/regress/sql/incremental_matview.sql diff --git a/src/test/isolation/isolation_schedule b/src/test/isolation/isolation_schedule index 15c33fad4c5..111fd465207 100644 --- a/src/test/isolation/isolation_schedule +++ b/src/test/isolation/isolation_schedule @@ -127,3 +127,12 @@ test: matview-write-skew test: lock-nowait test: for-portion-of test: ddl-dependency-locking +test: ivm-create-insert +test: ivm-create-insert2 +test: ivm-create-insert3 +test: ivm-insert-insert +test: ivm-insert-insert2 +test: ivm-insert-insert3 +test: ivm-refresh-insert +test: ivm-refresh-insert2 +test: ivm-refresh-insert3 diff --git a/src/test/regress/expected/incremental_matview.out b/src/test/regress/expected/incremental_matview.out new file mode 100644 index 00000000000..f215aa88e48 --- /dev/null +++ b/src/test/regress/expected/incremental_matview.out @@ -0,0 +1,1100 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ERROR: materialized view "mv_ivm_1" has not been populated +HINT: Use the REFRESH MATERIALIZED VIEW command. +REFRESH MATERIALIZED VIEW mv_ivm_1; +NOTICE: could not create an index on materialized view "mv_ivm_1" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 17 +(1 row) + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 1 +(1 row) + +ROLLBACK; +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_rename_index" on materialized view "mv_ivm_rename" +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +ERROR: IVM column can not be renamed +DROP MATERIALIZED VIEW mv_ivm_rename; +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_unique_index" on materialized view "mv_ivm_unique" +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +ERROR: unique index creation on IVM columns is not supported +DROP MATERIALIZED VIEW mv_ivm_unique; +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +NOTICE: could not create an index on materialized view "mv_ivm_func" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +NOTICE: could not create an index on materialized view "mv_ivm_no_tbl" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_duplicate" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +NOTICE: created index "mv_ivm_distinct_index" on materialized view "mv_ivm_distinct" +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 20 + 30 + 40 + 50 +(6 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +ROLLBACK; +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 120 | 2 | 60.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+---------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 220 | 2 | 110.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 20 | 1 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 120 | 2 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; + sum | count +-----+------- +(0 rows) + +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; + i | sum | count +---+-----+------- +(0 rows) + +ROLLBACK; +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 150 | 5 | 30.0000000000000000 +(1 row) + +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 210 | 6 | 35.0000000000000000 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +NOTICE: created index "mv_ivm_avg_bug_index" on materialized view "mv_ivm_avg_bug" +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 3 | 3.3333333333333333 + 2 | 80 | 3 | 26.6666666666666667 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_min_max_index" on materialized view "mv_ivm_min_max" +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 10 + 2 | 20 | 20 + 3 | 30 | 30 + 4 | 40 | 40 + 5 | 50 | 50 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 12 + 2 | 20 | 22 + 3 | 30 | 32 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 11 | 12 + 2 | 20 | 22 + 3 | 30 | 31 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min_max" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 50 +(1 row) + +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 0 | 70 +(1 row) + +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 60 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + | +(1 row) + +ROLLBACK; +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min; + min +----- + 10 +(1 row) + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + min +----- + 20 +(1 row) + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; + min +----- + 30 +(1 row) + +ROLLBACK; +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | sum +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | b +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ERROR: too many column names were specified +ROLLBACK; +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +NOTICE: could not create an index on materialized view "mv_self" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +----+---- + 10 | 10 + 20 | 20 + 30 | 30 +(3 rows) + +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 30 | 30 + 40 | 40 + 200 | 200 +(3 rows) + +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 130 | 130 + 300 | 300 +(4 rows) + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 70 | 70 + 70 | 77 + 77 | 70 + 77 | 77 + 130 | 130 + 300 | 300 +(8 rows) + +ROLLBACK; +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY v1; + v1 | v2 +----+----- + 10 | 100 + 20 | 200 + 30 | 300 +(3 rows) + +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv ORDER BY v1; + v1 | v2 +------+----- + 10 | 100 + 11 | 100 + 1020 | 200 + 1020 | 222 +(4 rows) + +ROLLBACK; +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +NOTICE: created index "mv_ri_index" on materialized view "mv_ri" +SELECT * FROM mv_ri ORDER BY i1; + i1 | i2 +----+---- + 1 | 1 + 2 | 2 + 3 | 3 +(3 rows) + +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; + i1 | i2 +----+---- + 3 | 3 + 10 | 10 +(2 rows) + +ROLLBACK; +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | +(2 rows) + +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | 20 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i +--- +(0 rows) + +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; + i +--- + 1 + +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 30 + | 3 +(2 rows) + +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 300 + | 30 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 1 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 4 +(1 row) + +ROLLBACK; +-- IMMV containing user defined type +BEGIN; +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: return type mytype is only a shell +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: argument type mytype is only a shell +LINE 1: CREATE FUNCTION mytype_out(mytype) + ^ +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +NOTICE: could not create an index on materialized view "mv_mytype" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + x +--- + 1 +(1 row) + +ROLLBACK; +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +ERROR: OUTER JOIN is not supported on incrementally maintainable materialized view +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +ERROR: CTE is not supported on incrementally maintainable materialized view +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +ERROR: ORDER BY clause is not supported on incrementally maintainable materialized view +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; +ERROR: HAVING clause is not supported on incrementally maintainable materialized view +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; +ERROR: mutable function is not supported on incrementally maintainable materialized view +HINT: functions must be marked IMMUTABLE +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; +ERROR: LIMIT/OFFSET clause is not supported on incrementally maintainable materialized view +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; +ERROR: DISTINCT ON is not supported on incrementally maintainable materialized view +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); +ERROR: TABLESAMPLE clause is not supported on incrementally maintainable materialized view +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; +ERROR: window functions are not supported on incrementally maintainable materialized view +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +ERROR: aggregate function with FILTER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +ERROR: aggregate function with DISTINCT arguments is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +ERROR: aggregate function with ORDER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); +ERROR: GROUPING SETS, ROLLUP, or CUBE clauses is not supported on incrementally maintainable materialized view +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ERROR: inheritance parent is not supported on incrementally maintainable materialized view +ROLLBACK; +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; +ERROR: UNION/INTERSECT/EXCEPT statements are not supported on incrementally maintainable materialized view +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; +ERROR: empty target list is not supported on incrementally maintainable materialized view +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; +ERROR: FOR UPDATE/SHARE clause is not supported on incrementally maintainable materialized view +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; +ERROR: column name __ivm_count__ is not supported on incrementally maintainable materialized view +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; +ERROR: GROUP BY expression not appearing in select list is not supported on incrementally maintainable materialized view +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); +ERROR: VALUES is not supported on incrementally maintainable materialized view +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +NOTICE: role "regress_ivm_admin" does not exist, skipping +DROP USER IF EXISTS regress_ivm_user; +NOTICE: role "regress_ivm_user" does not exist, skipping +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +NOTICE: could not create an index on materialized view "ivm_rls" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user +(1 row) + +RESET SESSION AUTHORIZATION; +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user + 3 | baz | regress_ivm_user +(2 rows) + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +-- +(1 row) + +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+-------+------------------ + 2 | bar | regress_ivm_user + 3 | baz | regress_ivm_user + 6 | corge | regress_ivm_user +(3 rows) + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +NOTICE: could not create an index on materialized view "ivm_rls2" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +RESET SESSION AUTHORIZATION; +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +-- +(1 row) + +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + id | data | owner | num +----+-------+------------------+--------- + 2 | bar | regress_ivm_user | two + 3 | baz_2 | regress_ivm_user | three_2 + 6 | corge | regress_ivm_user | six +(3 rows) + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +NOTICE: could not create an index on materialized view "mv_update_same" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + i +--- + 2 +(1 row) + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +NOTICE: created index "mv_self_ref_index" on materialized view "mv_self_ref" +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; + a | b +----+---- + 11 | + 12 | 11 + 13 | 12 +(3 rows) + +ROLLBACK; +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; +NOTICE: created index "mv_idx1_index" on materialized view "mv_idx1" +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; +NOTICE: created index "mv_idx2_index" on materialized view "mv_idx2" +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; +NOTICE: created index "mv_idx3_index" on materialized view "mv_idx3" +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +NOTICE: could not create an index on materialized view "mv_idx4" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; +NOTICE: could not create an index on materialized view "mv_idx5" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); +NOTICE: could not create an index on materialized view "mv_idx6" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ERROR: data type json has no default operator class for access method "btree" +ROLLBACK; +-- cleanup +DROP TABLE rls_tbl CASCADE; +NOTICE: drop cascades to 2 other objects +DETAIL: drop cascades to materialized view ivm_rls +drop cascades to materialized view ivm_rls2 +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; +DROP TABLE mv_base_b CASCADE; +NOTICE: drop cascades to 3 other objects +DETAIL: drop cascades to materialized view mv_ivm_1 +drop cascades to view b_view +drop cascades to materialized view b_mview +DROP TABLE mv_base_a CASCADE; diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index 8fa0a6c47fb..7caca5f64fd 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -77,6 +77,7 @@ test: brin_bloom brin_multi # Another group of parallel tests # ---------- test: create_table_like alter_generic alter_operator misc async dbsize merge misc_functions nls sysviews tsrf tid tidscan tidrangescan collate.utf8 collate.icu.utf8 incremental_sort create_role without_overlaps generated_virtual +test: incremental_matview # collate.linux.utf8 and collate.icu.utf8 tests cannot be run in parallel with each other # psql depends on create_am diff --git a/src/test/regress/sql/incremental_matview.sql b/src/test/regress/sql/incremental_matview.sql new file mode 100644 index 00000000000..2d55c393d6f --- /dev/null +++ b/src/test/regress/sql/incremental_matview.sql @@ -0,0 +1,580 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); + +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +REFRESH MATERIALIZED VIEW mv_ivm_1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; + +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; +ROLLBACK; + +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +DROP MATERIALIZED VIEW mv_ivm_rename; + +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +DROP MATERIALIZED VIEW mv_ivm_unique; + +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; + + +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +ROLLBACK; + +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +ROLLBACK; + +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +ROLLBACK; + +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +ROLLBACK; + +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +ROLLBACK; + +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min; + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); + +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; +ROLLBACK; + +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +SELECT * FROM mv_self ORDER BY v1; +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; +SELECT * FROM mv_self ORDER BY v1; + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + +ROLLBACK; + +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +SELECT * FROM mv ORDER BY v1; +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; +SELECT * FROM mv ORDER BY v1; +ROLLBACK; + +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +SELECT * FROM mv_ri ORDER BY i1; +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; +ROLLBACK; + +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +-- IMMV containing user defined type +BEGIN; + +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); + +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; + +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); + +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); + +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + +ROLLBACK; + +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; + +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; + +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; + +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; + +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; + +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); + +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; + +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); + +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ROLLBACK; + +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; + +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; + +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; + +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; + +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; + +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; + +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); + +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +DROP USER IF EXISTS regress_ivm_user; +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; + +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); + +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; + +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; + +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; +RESET SESSION AUTHORIZATION; + +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +RESET SESSION AUTHORIZATION; + +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; +ROLLBACK; + +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); + +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; + +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; + +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; + +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; + +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); + +ROLLBACK; + +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ROLLBACK; + +-- cleanup + +DROP TABLE rls_tbl CASCADE; +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; + +DROP TABLE mv_base_b CASCADE; +DROP TABLE mv_base_a CASCADE; -- 2.43.0 --Multipart=_Fri__29_May_2026_23_14_17_+0900_Te0o73X2VqYK57Gd Content-Type: text/x-diff; name="v37-0009-Add-support-for-min-max-aggregates-for-IVM.patch" Content-Disposition: attachment; filename="v37-0009-Add-support-for-min-max-aggregates-for-IVM.patch" Content-Transfer-Encoding: 7bit ^ permalink raw reply [nested|flat] 78+ messages in thread
* [PATCH v37 10/11] Add regression tests for Incremental View Maintenance @ 2026-05-29 09:31 Yugo Nagata <[email protected]> 0 siblings, 0 replies; 78+ messages in thread From: Yugo Nagata @ 2026-05-29 09:31 UTC (permalink / raw) --- src/test/isolation/isolation_schedule | 9 + .../regress/expected/incremental_matview.out | 1100 +++++++++++++++++ src/test/regress/parallel_schedule | 1 + src/test/regress/sql/incremental_matview.sql | 580 +++++++++ 4 files changed, 1690 insertions(+) create mode 100644 src/test/regress/expected/incremental_matview.out create mode 100644 src/test/regress/sql/incremental_matview.sql diff --git a/src/test/isolation/isolation_schedule b/src/test/isolation/isolation_schedule index 15c33fad4c5..111fd465207 100644 --- a/src/test/isolation/isolation_schedule +++ b/src/test/isolation/isolation_schedule @@ -127,3 +127,12 @@ test: matview-write-skew test: lock-nowait test: for-portion-of test: ddl-dependency-locking +test: ivm-create-insert +test: ivm-create-insert2 +test: ivm-create-insert3 +test: ivm-insert-insert +test: ivm-insert-insert2 +test: ivm-insert-insert3 +test: ivm-refresh-insert +test: ivm-refresh-insert2 +test: ivm-refresh-insert3 diff --git a/src/test/regress/expected/incremental_matview.out b/src/test/regress/expected/incremental_matview.out new file mode 100644 index 00000000000..f215aa88e48 --- /dev/null +++ b/src/test/regress/expected/incremental_matview.out @@ -0,0 +1,1100 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ERROR: materialized view "mv_ivm_1" has not been populated +HINT: Use the REFRESH MATERIALIZED VIEW command. +REFRESH MATERIALIZED VIEW mv_ivm_1; +NOTICE: could not create an index on materialized view "mv_ivm_1" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 17 +(1 row) + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 1 +(1 row) + +ROLLBACK; +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_rename_index" on materialized view "mv_ivm_rename" +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +ERROR: IVM column can not be renamed +DROP MATERIALIZED VIEW mv_ivm_rename; +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_unique_index" on materialized view "mv_ivm_unique" +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +ERROR: unique index creation on IVM columns is not supported +DROP MATERIALIZED VIEW mv_ivm_unique; +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +NOTICE: could not create an index on materialized view "mv_ivm_func" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +NOTICE: could not create an index on materialized view "mv_ivm_no_tbl" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_duplicate" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +NOTICE: created index "mv_ivm_distinct_index" on materialized view "mv_ivm_distinct" +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 20 + 30 + 40 + 50 +(6 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +ROLLBACK; +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 120 | 2 | 60.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+---------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 220 | 2 | 110.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 20 | 1 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 120 | 2 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; + sum | count +-----+------- +(0 rows) + +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; + i | sum | count +---+-----+------- +(0 rows) + +ROLLBACK; +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 150 | 5 | 30.0000000000000000 +(1 row) + +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 210 | 6 | 35.0000000000000000 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +NOTICE: created index "mv_ivm_avg_bug_index" on materialized view "mv_ivm_avg_bug" +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 3 | 3.3333333333333333 + 2 | 80 | 3 | 26.6666666666666667 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_min_max_index" on materialized view "mv_ivm_min_max" +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 10 + 2 | 20 | 20 + 3 | 30 | 30 + 4 | 40 | 40 + 5 | 50 | 50 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 12 + 2 | 20 | 22 + 3 | 30 | 32 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 11 | 12 + 2 | 20 | 22 + 3 | 30 | 31 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min_max" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 50 +(1 row) + +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 0 | 70 +(1 row) + +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 60 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + | +(1 row) + +ROLLBACK; +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min; + min +----- + 10 +(1 row) + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + min +----- + 20 +(1 row) + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; + min +----- + 30 +(1 row) + +ROLLBACK; +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | sum +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | b +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ERROR: too many column names were specified +ROLLBACK; +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +NOTICE: could not create an index on materialized view "mv_self" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +----+---- + 10 | 10 + 20 | 20 + 30 | 30 +(3 rows) + +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 30 | 30 + 40 | 40 + 200 | 200 +(3 rows) + +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 130 | 130 + 300 | 300 +(4 rows) + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 70 | 70 + 70 | 77 + 77 | 70 + 77 | 77 + 130 | 130 + 300 | 300 +(8 rows) + +ROLLBACK; +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY v1; + v1 | v2 +----+----- + 10 | 100 + 20 | 200 + 30 | 300 +(3 rows) + +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv ORDER BY v1; + v1 | v2 +------+----- + 10 | 100 + 11 | 100 + 1020 | 200 + 1020 | 222 +(4 rows) + +ROLLBACK; +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +NOTICE: created index "mv_ri_index" on materialized view "mv_ri" +SELECT * FROM mv_ri ORDER BY i1; + i1 | i2 +----+---- + 1 | 1 + 2 | 2 + 3 | 3 +(3 rows) + +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; + i1 | i2 +----+---- + 3 | 3 + 10 | 10 +(2 rows) + +ROLLBACK; +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | +(2 rows) + +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | 20 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i +--- +(0 rows) + +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; + i +--- + 1 + +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 30 + | 3 +(2 rows) + +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 300 + | 30 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 1 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 4 +(1 row) + +ROLLBACK; +-- IMMV containing user defined type +BEGIN; +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: return type mytype is only a shell +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: argument type mytype is only a shell +LINE 1: CREATE FUNCTION mytype_out(mytype) + ^ +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +NOTICE: could not create an index on materialized view "mv_mytype" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + x +--- + 1 +(1 row) + +ROLLBACK; +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +ERROR: OUTER JOIN is not supported on incrementally maintainable materialized view +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +ERROR: CTE is not supported on incrementally maintainable materialized view +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +ERROR: ORDER BY clause is not supported on incrementally maintainable materialized view +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; +ERROR: HAVING clause is not supported on incrementally maintainable materialized view +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; +ERROR: mutable function is not supported on incrementally maintainable materialized view +HINT: functions must be marked IMMUTABLE +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; +ERROR: LIMIT/OFFSET clause is not supported on incrementally maintainable materialized view +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; +ERROR: DISTINCT ON is not supported on incrementally maintainable materialized view +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); +ERROR: TABLESAMPLE clause is not supported on incrementally maintainable materialized view +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; +ERROR: window functions are not supported on incrementally maintainable materialized view +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +ERROR: aggregate function with FILTER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +ERROR: aggregate function with DISTINCT arguments is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +ERROR: aggregate function with ORDER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); +ERROR: GROUPING SETS, ROLLUP, or CUBE clauses is not supported on incrementally maintainable materialized view +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ERROR: inheritance parent is not supported on incrementally maintainable materialized view +ROLLBACK; +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; +ERROR: UNION/INTERSECT/EXCEPT statements are not supported on incrementally maintainable materialized view +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; +ERROR: empty target list is not supported on incrementally maintainable materialized view +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; +ERROR: FOR UPDATE/SHARE clause is not supported on incrementally maintainable materialized view +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; +ERROR: column name __ivm_count__ is not supported on incrementally maintainable materialized view +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; +ERROR: GROUP BY expression not appearing in select list is not supported on incrementally maintainable materialized view +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); +ERROR: VALUES is not supported on incrementally maintainable materialized view +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +NOTICE: role "regress_ivm_admin" does not exist, skipping +DROP USER IF EXISTS regress_ivm_user; +NOTICE: role "regress_ivm_user" does not exist, skipping +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +NOTICE: could not create an index on materialized view "ivm_rls" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user +(1 row) + +RESET SESSION AUTHORIZATION; +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user + 3 | baz | regress_ivm_user +(2 rows) + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +-- +(1 row) + +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+-------+------------------ + 2 | bar | regress_ivm_user + 3 | baz | regress_ivm_user + 6 | corge | regress_ivm_user +(3 rows) + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +NOTICE: could not create an index on materialized view "ivm_rls2" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +RESET SESSION AUTHORIZATION; +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +-- +(1 row) + +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + id | data | owner | num +----+-------+------------------+--------- + 2 | bar | regress_ivm_user | two + 3 | baz_2 | regress_ivm_user | three_2 + 6 | corge | regress_ivm_user | six +(3 rows) + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +NOTICE: could not create an index on materialized view "mv_update_same" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + i +--- + 2 +(1 row) + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +NOTICE: created index "mv_self_ref_index" on materialized view "mv_self_ref" +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; + a | b +----+---- + 11 | + 12 | 11 + 13 | 12 +(3 rows) + +ROLLBACK; +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; +NOTICE: created index "mv_idx1_index" on materialized view "mv_idx1" +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; +NOTICE: created index "mv_idx2_index" on materialized view "mv_idx2" +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; +NOTICE: created index "mv_idx3_index" on materialized view "mv_idx3" +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +NOTICE: could not create an index on materialized view "mv_idx4" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; +NOTICE: could not create an index on materialized view "mv_idx5" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); +NOTICE: could not create an index on materialized view "mv_idx6" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ERROR: data type json has no default operator class for access method "btree" +ROLLBACK; +-- cleanup +DROP TABLE rls_tbl CASCADE; +NOTICE: drop cascades to 2 other objects +DETAIL: drop cascades to materialized view ivm_rls +drop cascades to materialized view ivm_rls2 +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; +DROP TABLE mv_base_b CASCADE; +NOTICE: drop cascades to 3 other objects +DETAIL: drop cascades to materialized view mv_ivm_1 +drop cascades to view b_view +drop cascades to materialized view b_mview +DROP TABLE mv_base_a CASCADE; diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index 8fa0a6c47fb..7caca5f64fd 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -77,6 +77,7 @@ test: brin_bloom brin_multi # Another group of parallel tests # ---------- test: create_table_like alter_generic alter_operator misc async dbsize merge misc_functions nls sysviews tsrf tid tidscan tidrangescan collate.utf8 collate.icu.utf8 incremental_sort create_role without_overlaps generated_virtual +test: incremental_matview # collate.linux.utf8 and collate.icu.utf8 tests cannot be run in parallel with each other # psql depends on create_am diff --git a/src/test/regress/sql/incremental_matview.sql b/src/test/regress/sql/incremental_matview.sql new file mode 100644 index 00000000000..2d55c393d6f --- /dev/null +++ b/src/test/regress/sql/incremental_matview.sql @@ -0,0 +1,580 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); + +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +REFRESH MATERIALIZED VIEW mv_ivm_1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; + +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; +ROLLBACK; + +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +DROP MATERIALIZED VIEW mv_ivm_rename; + +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +DROP MATERIALIZED VIEW mv_ivm_unique; + +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; + + +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +ROLLBACK; + +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +ROLLBACK; + +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +ROLLBACK; + +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +ROLLBACK; + +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +ROLLBACK; + +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min; + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); + +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; +ROLLBACK; + +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +SELECT * FROM mv_self ORDER BY v1; +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; +SELECT * FROM mv_self ORDER BY v1; + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + +ROLLBACK; + +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +SELECT * FROM mv ORDER BY v1; +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; +SELECT * FROM mv ORDER BY v1; +ROLLBACK; + +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +SELECT * FROM mv_ri ORDER BY i1; +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; +ROLLBACK; + +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +-- IMMV containing user defined type +BEGIN; + +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); + +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; + +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); + +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); + +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + +ROLLBACK; + +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; + +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; + +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; + +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; + +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; + +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); + +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; + +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); + +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ROLLBACK; + +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; + +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; + +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; + +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; + +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; + +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; + +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); + +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +DROP USER IF EXISTS regress_ivm_user; +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; + +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); + +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; + +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; + +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; +RESET SESSION AUTHORIZATION; + +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +RESET SESSION AUTHORIZATION; + +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; +ROLLBACK; + +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); + +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; + +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; + +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; + +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; + +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); + +ROLLBACK; + +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ROLLBACK; + +-- cleanup + +DROP TABLE rls_tbl CASCADE; +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; + +DROP TABLE mv_base_b CASCADE; +DROP TABLE mv_base_a CASCADE; -- 2.43.0 --Multipart=_Fri__29_May_2026_23_14_17_+0900_Te0o73X2VqYK57Gd Content-Type: text/x-diff; name="v37-0009-Add-support-for-min-max-aggregates-for-IVM.patch" Content-Disposition: attachment; filename="v37-0009-Add-support-for-min-max-aggregates-for-IVM.patch" Content-Transfer-Encoding: 7bit ^ permalink raw reply [nested|flat] 78+ messages in thread
* [PATCH v38 10/11] Add regression tests for Incremental View Maintenance @ 2026-05-29 09:31 Yugo Nagata <[email protected]> 0 siblings, 0 replies; 78+ messages in thread From: Yugo Nagata @ 2026-05-29 09:31 UTC (permalink / raw) --- .../isolation/expected/ivm-create-insert.out | 285 +++++ .../isolation/expected/ivm-create-insert2.out | 305 +++++ .../isolation/expected/ivm-create-insert3.out | 305 +++++ .../isolation/expected/ivm-insert-insert.out | 497 ++++++++ .../isolation/expected/ivm-insert-insert2.out | 373 ++++++ .../isolation/expected/ivm-insert-insert3.out | 373 ++++++ .../isolation/expected/ivm-refresh-insert.out | 213 ++++ .../expected/ivm-refresh-insert2.out | 191 +++ .../expected/ivm-refresh-insert3.out | 191 +++ src/test/isolation/isolation_schedule | 9 + .../isolation/specs/ivm-create-insert.spec | 47 + .../isolation/specs/ivm-create-insert2.spec | 54 + .../isolation/specs/ivm-create-insert3.spec | 54 + .../isolation/specs/ivm-insert-insert.spec | 62 + .../isolation/specs/ivm-insert-insert2.spec | 62 + .../isolation/specs/ivm-insert-insert3.spec | 62 + .../isolation/specs/ivm-refresh-insert.spec | 46 + .../isolation/specs/ivm-refresh-insert2.spec | 46 + .../isolation/specs/ivm-refresh-insert3.spec | 46 + .../regress/expected/incremental_matview.out | 1100 +++++++++++++++++ src/test/regress/parallel_schedule | 1 + src/test/regress/sql/incremental_matview.sql | 580 +++++++++ 22 files changed, 4902 insertions(+) create mode 100644 src/test/isolation/expected/ivm-create-insert.out create mode 100644 src/test/isolation/expected/ivm-create-insert2.out create mode 100644 src/test/isolation/expected/ivm-create-insert3.out create mode 100644 src/test/isolation/expected/ivm-insert-insert.out create mode 100644 src/test/isolation/expected/ivm-insert-insert2.out create mode 100644 src/test/isolation/expected/ivm-insert-insert3.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert2.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert3.out create mode 100644 src/test/isolation/specs/ivm-create-insert.spec create mode 100644 src/test/isolation/specs/ivm-create-insert2.spec create mode 100644 src/test/isolation/specs/ivm-create-insert3.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert2.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert3.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert2.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert3.spec create mode 100644 src/test/regress/expected/incremental_matview.out create mode 100644 src/test/regress/sql/incremental_matview.sql diff --git a/src/test/isolation/expected/ivm-create-insert.out b/src/test/isolation/expected/ivm-create-insert.out new file mode 100644 index 00000000000..5da00043aba --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert.out @@ -0,0 +1,285 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-create-insert2.out b/src/test/isolation/expected/ivm-create-insert2.out new file mode 100644 index 00000000000..907d892c6d4 --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert2.out @@ -0,0 +1,305 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + diff --git a/src/test/isolation/expected/ivm-create-insert3.out b/src/test/isolation/expected/ivm-create-insert3.out new file mode 100644 index 00000000000..907d892c6d4 --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert3.out @@ -0,0 +1,305 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert.out b/src/test/isolation/expected/ivm-insert-insert.out new file mode 100644 index 00000000000..5ca4cfea677 --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert.out @@ -0,0 +1,497 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; <waiting ...> +step c1: COMMIT; +step update2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; <waiting ...> +step c1: COMMIT; +step update2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; <waiting ...> +step c2: COMMIT; +step update1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; <waiting ...> +step c2: COMMIT; +step update1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); <waiting ...> +step c1: COMMIT; +step insert2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); <waiting ...> +step c1: COMMIT; +step insert2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); <waiting ...> +step c2: COMMIT; +step insert1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); <waiting ...> +step c2: COMMIT; +step insert1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert2.out b/src/test/isolation/expected/ivm-insert-insert2.out new file mode 100644 index 00000000000..e1c66d4de5e --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert2.out @@ -0,0 +1,373 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert3.out b/src/test/isolation/expected/ivm-insert-insert3.out new file mode 100644 index 00000000000..e1c66d4de5e --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert3.out @@ -0,0 +1,373 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert.out b/src/test/isolation/expected/ivm-refresh-insert.out new file mode 100644 index 00000000000..a925938bf1c --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert.out @@ -0,0 +1,213 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert2.out b/src/test/isolation/expected/ivm-refresh-insert2.out new file mode 100644 index 00000000000..dc1b16ae34e --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert2.out @@ -0,0 +1,191 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert3.out b/src/test/isolation/expected/ivm-refresh-insert3.out new file mode 100644 index 00000000000..dc1b16ae34e --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert3.out @@ -0,0 +1,191 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/isolation_schedule b/src/test/isolation/isolation_schedule index b8ebe92553c..6b7e873b370 100644 --- a/src/test/isolation/isolation_schedule +++ b/src/test/isolation/isolation_schedule @@ -128,3 +128,12 @@ test: matview-write-skew test: lock-nowait test: for-portion-of test: ddl-dependency-locking +test: ivm-create-insert +test: ivm-create-insert2 +test: ivm-create-insert3 +test: ivm-insert-insert +test: ivm-insert-insert2 +test: ivm-insert-insert3 +test: ivm-refresh-insert +test: ivm-refresh-insert2 +test: ivm-refresh-insert3 diff --git a/src/test/isolation/specs/ivm-create-insert.spec b/src/test/isolation/specs/ivm-create-insert.spec new file mode 100644 index 00000000000..ccd6fd080a9 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert.spec @@ -0,0 +1,47 @@ +# Test interaction between concurrent transactions performing +# create and insert in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-create-insert2.spec b/src/test/isolation/specs/ivm-create-insert2.spec new file mode 100644 index 00000000000..02cec85ae07 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert2.spec @@ -0,0 +1,54 @@ +# Test interaction between concurrent transactions performing +# create and insert in REPEATABLE READ isolation level +# +# Note: +# In this isolation level, it is possible that create_immv could +# create an inconsistent view not including effects of a concurrent +# transaction. So, an warning message is raised to suggest using it +# in READ COMMITTED or executing refresh_immv to make sure to +# make the view contents consistent. + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-create-insert3.spec b/src/test/isolation/specs/ivm-create-insert3.spec new file mode 100644 index 00000000000..19ce03185a4 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert3.spec @@ -0,0 +1,54 @@ +# Test interaction between concurrent transactions performing +# create and insert in SERIALIZABLE isolation level +# +# Note: +# In this isolation level, it is possible that create_immv could +# create an inconsistent view not including effects of a concurrent +# transaction. So, an warning message is raised to suggest using it +# in READ COMMITTED or executing refresh_immv to make sure to +# make the view contents consistent. + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert.spec b/src/test/isolation/specs/ivm-insert-insert.spec new file mode 100644 index 00000000000..b8f794ca191 --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert2.spec b/src/test/isolation/specs/ivm-insert-insert2.spec new file mode 100644 index 00000000000..ed086d1ba1e --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert2.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in REPEATABLE READ isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert3.spec b/src/test/isolation/specs/ivm-insert-insert3.spec new file mode 100644 index 00000000000..b18bd121033 --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert3.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in SERIALIZABLE isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert.spec b/src/test/isolation/specs/ivm-refresh-insert.spec new file mode 100644 index 00000000000..d7181251962 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert2.spec b/src/test/isolation/specs/ivm-refresh-insert2.spec new file mode 100644 index 00000000000..f2d1d5013f2 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert2.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in REPEATABLE READ isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert3.spec b/src/test/isolation/specs/ivm-refresh-insert3.spec new file mode 100644 index 00000000000..0ec2b1d1de0 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert3.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in SERIALIZABLE isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/regress/expected/incremental_matview.out b/src/test/regress/expected/incremental_matview.out new file mode 100644 index 00000000000..f215aa88e48 --- /dev/null +++ b/src/test/regress/expected/incremental_matview.out @@ -0,0 +1,1100 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ERROR: materialized view "mv_ivm_1" has not been populated +HINT: Use the REFRESH MATERIALIZED VIEW command. +REFRESH MATERIALIZED VIEW mv_ivm_1; +NOTICE: could not create an index on materialized view "mv_ivm_1" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 17 +(1 row) + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 1 +(1 row) + +ROLLBACK; +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_rename_index" on materialized view "mv_ivm_rename" +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +ERROR: IVM column can not be renamed +DROP MATERIALIZED VIEW mv_ivm_rename; +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_unique_index" on materialized view "mv_ivm_unique" +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +ERROR: unique index creation on IVM columns is not supported +DROP MATERIALIZED VIEW mv_ivm_unique; +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +NOTICE: could not create an index on materialized view "mv_ivm_func" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +NOTICE: could not create an index on materialized view "mv_ivm_no_tbl" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_duplicate" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +NOTICE: created index "mv_ivm_distinct_index" on materialized view "mv_ivm_distinct" +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 20 + 30 + 40 + 50 +(6 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +ROLLBACK; +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 120 | 2 | 60.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+---------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 220 | 2 | 110.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 20 | 1 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 120 | 2 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; + sum | count +-----+------- +(0 rows) + +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; + i | sum | count +---+-----+------- +(0 rows) + +ROLLBACK; +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 150 | 5 | 30.0000000000000000 +(1 row) + +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 210 | 6 | 35.0000000000000000 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +NOTICE: created index "mv_ivm_avg_bug_index" on materialized view "mv_ivm_avg_bug" +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 3 | 3.3333333333333333 + 2 | 80 | 3 | 26.6666666666666667 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_min_max_index" on materialized view "mv_ivm_min_max" +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 10 + 2 | 20 | 20 + 3 | 30 | 30 + 4 | 40 | 40 + 5 | 50 | 50 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 12 + 2 | 20 | 22 + 3 | 30 | 32 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 11 | 12 + 2 | 20 | 22 + 3 | 30 | 31 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min_max" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 50 +(1 row) + +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 0 | 70 +(1 row) + +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 60 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + | +(1 row) + +ROLLBACK; +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min; + min +----- + 10 +(1 row) + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + min +----- + 20 +(1 row) + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; + min +----- + 30 +(1 row) + +ROLLBACK; +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | sum +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | b +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ERROR: too many column names were specified +ROLLBACK; +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +NOTICE: could not create an index on materialized view "mv_self" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +----+---- + 10 | 10 + 20 | 20 + 30 | 30 +(3 rows) + +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 30 | 30 + 40 | 40 + 200 | 200 +(3 rows) + +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 130 | 130 + 300 | 300 +(4 rows) + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 70 | 70 + 70 | 77 + 77 | 70 + 77 | 77 + 130 | 130 + 300 | 300 +(8 rows) + +ROLLBACK; +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY v1; + v1 | v2 +----+----- + 10 | 100 + 20 | 200 + 30 | 300 +(3 rows) + +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv ORDER BY v1; + v1 | v2 +------+----- + 10 | 100 + 11 | 100 + 1020 | 200 + 1020 | 222 +(4 rows) + +ROLLBACK; +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +NOTICE: created index "mv_ri_index" on materialized view "mv_ri" +SELECT * FROM mv_ri ORDER BY i1; + i1 | i2 +----+---- + 1 | 1 + 2 | 2 + 3 | 3 +(3 rows) + +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; + i1 | i2 +----+---- + 3 | 3 + 10 | 10 +(2 rows) + +ROLLBACK; +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | +(2 rows) + +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | 20 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i +--- +(0 rows) + +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; + i +--- + 1 + +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 30 + | 3 +(2 rows) + +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 300 + | 30 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 1 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 4 +(1 row) + +ROLLBACK; +-- IMMV containing user defined type +BEGIN; +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: return type mytype is only a shell +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: argument type mytype is only a shell +LINE 1: CREATE FUNCTION mytype_out(mytype) + ^ +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +NOTICE: could not create an index on materialized view "mv_mytype" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + x +--- + 1 +(1 row) + +ROLLBACK; +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +ERROR: OUTER JOIN is not supported on incrementally maintainable materialized view +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +ERROR: CTE is not supported on incrementally maintainable materialized view +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +ERROR: ORDER BY clause is not supported on incrementally maintainable materialized view +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; +ERROR: HAVING clause is not supported on incrementally maintainable materialized view +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; +ERROR: mutable function is not supported on incrementally maintainable materialized view +HINT: functions must be marked IMMUTABLE +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; +ERROR: LIMIT/OFFSET clause is not supported on incrementally maintainable materialized view +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; +ERROR: DISTINCT ON is not supported on incrementally maintainable materialized view +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); +ERROR: TABLESAMPLE clause is not supported on incrementally maintainable materialized view +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; +ERROR: window functions are not supported on incrementally maintainable materialized view +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +ERROR: aggregate function with FILTER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +ERROR: aggregate function with DISTINCT arguments is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +ERROR: aggregate function with ORDER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); +ERROR: GROUPING SETS, ROLLUP, or CUBE clauses is not supported on incrementally maintainable materialized view +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ERROR: inheritance parent is not supported on incrementally maintainable materialized view +ROLLBACK; +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; +ERROR: UNION/INTERSECT/EXCEPT statements are not supported on incrementally maintainable materialized view +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; +ERROR: empty target list is not supported on incrementally maintainable materialized view +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; +ERROR: FOR UPDATE/SHARE clause is not supported on incrementally maintainable materialized view +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; +ERROR: column name __ivm_count__ is not supported on incrementally maintainable materialized view +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; +ERROR: GROUP BY expression not appearing in select list is not supported on incrementally maintainable materialized view +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); +ERROR: VALUES is not supported on incrementally maintainable materialized view +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +NOTICE: role "regress_ivm_admin" does not exist, skipping +DROP USER IF EXISTS regress_ivm_user; +NOTICE: role "regress_ivm_user" does not exist, skipping +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +NOTICE: could not create an index on materialized view "ivm_rls" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user +(1 row) + +RESET SESSION AUTHORIZATION; +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user + 3 | baz | regress_ivm_user +(2 rows) + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +-- +(1 row) + +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+-------+------------------ + 2 | bar | regress_ivm_user + 3 | baz | regress_ivm_user + 6 | corge | regress_ivm_user +(3 rows) + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +NOTICE: could not create an index on materialized view "ivm_rls2" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +RESET SESSION AUTHORIZATION; +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +-- +(1 row) + +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + id | data | owner | num +----+-------+------------------+--------- + 2 | bar | regress_ivm_user | two + 3 | baz_2 | regress_ivm_user | three_2 + 6 | corge | regress_ivm_user | six +(3 rows) + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +NOTICE: could not create an index on materialized view "mv_update_same" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + i +--- + 2 +(1 row) + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +NOTICE: created index "mv_self_ref_index" on materialized view "mv_self_ref" +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; + a | b +----+---- + 11 | + 12 | 11 + 13 | 12 +(3 rows) + +ROLLBACK; +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; +NOTICE: created index "mv_idx1_index" on materialized view "mv_idx1" +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; +NOTICE: created index "mv_idx2_index" on materialized view "mv_idx2" +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; +NOTICE: created index "mv_idx3_index" on materialized view "mv_idx3" +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +NOTICE: could not create an index on materialized view "mv_idx4" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; +NOTICE: could not create an index on materialized view "mv_idx5" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); +NOTICE: could not create an index on materialized view "mv_idx6" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ERROR: data type json has no default operator class for access method "btree" +ROLLBACK; +-- cleanup +DROP TABLE rls_tbl CASCADE; +NOTICE: drop cascades to 2 other objects +DETAIL: drop cascades to materialized view ivm_rls +drop cascades to materialized view ivm_rls2 +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; +DROP TABLE mv_base_b CASCADE; +NOTICE: drop cascades to 3 other objects +DETAIL: drop cascades to materialized view mv_ivm_1 +drop cascades to view b_view +drop cascades to materialized view b_mview +DROP TABLE mv_base_a CASCADE; diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index 8fa0a6c47fb..7caca5f64fd 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -77,6 +77,7 @@ test: brin_bloom brin_multi # Another group of parallel tests # ---------- test: create_table_like alter_generic alter_operator misc async dbsize merge misc_functions nls sysviews tsrf tid tidscan tidrangescan collate.utf8 collate.icu.utf8 incremental_sort create_role without_overlaps generated_virtual +test: incremental_matview # collate.linux.utf8 and collate.icu.utf8 tests cannot be run in parallel with each other # psql depends on create_am diff --git a/src/test/regress/sql/incremental_matview.sql b/src/test/regress/sql/incremental_matview.sql new file mode 100644 index 00000000000..2d55c393d6f --- /dev/null +++ b/src/test/regress/sql/incremental_matview.sql @@ -0,0 +1,580 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); + +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +REFRESH MATERIALIZED VIEW mv_ivm_1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; + +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; +ROLLBACK; + +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +DROP MATERIALIZED VIEW mv_ivm_rename; + +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +DROP MATERIALIZED VIEW mv_ivm_unique; + +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; + + +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +ROLLBACK; + +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +ROLLBACK; + +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +ROLLBACK; + +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +ROLLBACK; + +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +ROLLBACK; + +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min; + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); + +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; +ROLLBACK; + +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +SELECT * FROM mv_self ORDER BY v1; +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; +SELECT * FROM mv_self ORDER BY v1; + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + +ROLLBACK; + +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +SELECT * FROM mv ORDER BY v1; +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; +SELECT * FROM mv ORDER BY v1; +ROLLBACK; + +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +SELECT * FROM mv_ri ORDER BY i1; +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; +ROLLBACK; + +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +-- IMMV containing user defined type +BEGIN; + +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); + +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; + +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); + +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); + +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + +ROLLBACK; + +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; + +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; + +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; + +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; + +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; + +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); + +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; + +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); + +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ROLLBACK; + +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; + +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; + +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; + +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; + +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; + +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; + +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); + +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +DROP USER IF EXISTS regress_ivm_user; +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; + +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); + +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; + +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; + +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; +RESET SESSION AUTHORIZATION; + +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +RESET SESSION AUTHORIZATION; + +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; +ROLLBACK; + +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); + +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; + +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; + +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; + +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; + +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); + +ROLLBACK; + +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ROLLBACK; + +-- cleanup + +DROP TABLE rls_tbl CASCADE; +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; + +DROP TABLE mv_base_b CASCADE; +DROP TABLE mv_base_a CASCADE; -- 2.43.0 --Multipart=_Wed__1_Jul_2026_00_04_01_+0900_OVSy2WWK_9aByzDJ Content-Type: text/x-diff; name="v38-0009-Add-support-for-min-max-aggregates-for-IVM.patch" Content-Disposition: attachment; filename="v38-0009-Add-support-for-min-max-aggregates-for-IVM.patch" Content-Transfer-Encoding: 7bit ^ permalink raw reply [nested|flat] 78+ messages in thread
* [PATCH v38 10/11] Add regression tests for Incremental View Maintenance @ 2026-05-29 09:31 Yugo Nagata <[email protected]> 0 siblings, 0 replies; 78+ messages in thread From: Yugo Nagata @ 2026-05-29 09:31 UTC (permalink / raw) --- .../isolation/expected/ivm-create-insert.out | 285 +++++ .../isolation/expected/ivm-create-insert2.out | 305 +++++ .../isolation/expected/ivm-create-insert3.out | 305 +++++ .../isolation/expected/ivm-insert-insert.out | 497 ++++++++ .../isolation/expected/ivm-insert-insert2.out | 373 ++++++ .../isolation/expected/ivm-insert-insert3.out | 373 ++++++ .../isolation/expected/ivm-refresh-insert.out | 213 ++++ .../expected/ivm-refresh-insert2.out | 191 +++ .../expected/ivm-refresh-insert3.out | 191 +++ src/test/isolation/isolation_schedule | 9 + .../isolation/specs/ivm-create-insert.spec | 47 + .../isolation/specs/ivm-create-insert2.spec | 54 + .../isolation/specs/ivm-create-insert3.spec | 54 + .../isolation/specs/ivm-insert-insert.spec | 62 + .../isolation/specs/ivm-insert-insert2.spec | 62 + .../isolation/specs/ivm-insert-insert3.spec | 62 + .../isolation/specs/ivm-refresh-insert.spec | 46 + .../isolation/specs/ivm-refresh-insert2.spec | 46 + .../isolation/specs/ivm-refresh-insert3.spec | 46 + .../regress/expected/incremental_matview.out | 1100 +++++++++++++++++ src/test/regress/parallel_schedule | 1 + src/test/regress/sql/incremental_matview.sql | 580 +++++++++ 22 files changed, 4902 insertions(+) create mode 100644 src/test/isolation/expected/ivm-create-insert.out create mode 100644 src/test/isolation/expected/ivm-create-insert2.out create mode 100644 src/test/isolation/expected/ivm-create-insert3.out create mode 100644 src/test/isolation/expected/ivm-insert-insert.out create mode 100644 src/test/isolation/expected/ivm-insert-insert2.out create mode 100644 src/test/isolation/expected/ivm-insert-insert3.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert2.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert3.out create mode 100644 src/test/isolation/specs/ivm-create-insert.spec create mode 100644 src/test/isolation/specs/ivm-create-insert2.spec create mode 100644 src/test/isolation/specs/ivm-create-insert3.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert2.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert3.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert2.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert3.spec create mode 100644 src/test/regress/expected/incremental_matview.out create mode 100644 src/test/regress/sql/incremental_matview.sql diff --git a/src/test/isolation/expected/ivm-create-insert.out b/src/test/isolation/expected/ivm-create-insert.out new file mode 100644 index 00000000000..5da00043aba --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert.out @@ -0,0 +1,285 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-create-insert2.out b/src/test/isolation/expected/ivm-create-insert2.out new file mode 100644 index 00000000000..907d892c6d4 --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert2.out @@ -0,0 +1,305 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + diff --git a/src/test/isolation/expected/ivm-create-insert3.out b/src/test/isolation/expected/ivm-create-insert3.out new file mode 100644 index 00000000000..907d892c6d4 --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert3.out @@ -0,0 +1,305 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert.out b/src/test/isolation/expected/ivm-insert-insert.out new file mode 100644 index 00000000000..5ca4cfea677 --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert.out @@ -0,0 +1,497 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; <waiting ...> +step c1: COMMIT; +step update2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; <waiting ...> +step c1: COMMIT; +step update2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; <waiting ...> +step c2: COMMIT; +step update1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; <waiting ...> +step c2: COMMIT; +step update1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); <waiting ...> +step c1: COMMIT; +step insert2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); <waiting ...> +step c1: COMMIT; +step insert2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); <waiting ...> +step c2: COMMIT; +step insert1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); <waiting ...> +step c2: COMMIT; +step insert1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert2.out b/src/test/isolation/expected/ivm-insert-insert2.out new file mode 100644 index 00000000000..e1c66d4de5e --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert2.out @@ -0,0 +1,373 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert3.out b/src/test/isolation/expected/ivm-insert-insert3.out new file mode 100644 index 00000000000..e1c66d4de5e --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert3.out @@ -0,0 +1,373 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert.out b/src/test/isolation/expected/ivm-refresh-insert.out new file mode 100644 index 00000000000..a925938bf1c --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert.out @@ -0,0 +1,213 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert2.out b/src/test/isolation/expected/ivm-refresh-insert2.out new file mode 100644 index 00000000000..dc1b16ae34e --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert2.out @@ -0,0 +1,191 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert3.out b/src/test/isolation/expected/ivm-refresh-insert3.out new file mode 100644 index 00000000000..dc1b16ae34e --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert3.out @@ -0,0 +1,191 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/isolation_schedule b/src/test/isolation/isolation_schedule index b8ebe92553c..6b7e873b370 100644 --- a/src/test/isolation/isolation_schedule +++ b/src/test/isolation/isolation_schedule @@ -128,3 +128,12 @@ test: matview-write-skew test: lock-nowait test: for-portion-of test: ddl-dependency-locking +test: ivm-create-insert +test: ivm-create-insert2 +test: ivm-create-insert3 +test: ivm-insert-insert +test: ivm-insert-insert2 +test: ivm-insert-insert3 +test: ivm-refresh-insert +test: ivm-refresh-insert2 +test: ivm-refresh-insert3 diff --git a/src/test/isolation/specs/ivm-create-insert.spec b/src/test/isolation/specs/ivm-create-insert.spec new file mode 100644 index 00000000000..ccd6fd080a9 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert.spec @@ -0,0 +1,47 @@ +# Test interaction between concurrent transactions performing +# create and insert in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-create-insert2.spec b/src/test/isolation/specs/ivm-create-insert2.spec new file mode 100644 index 00000000000..02cec85ae07 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert2.spec @@ -0,0 +1,54 @@ +# Test interaction between concurrent transactions performing +# create and insert in REPEATABLE READ isolation level +# +# Note: +# In this isolation level, it is possible that create_immv could +# create an inconsistent view not including effects of a concurrent +# transaction. So, an warning message is raised to suggest using it +# in READ COMMITTED or executing refresh_immv to make sure to +# make the view contents consistent. + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-create-insert3.spec b/src/test/isolation/specs/ivm-create-insert3.spec new file mode 100644 index 00000000000..19ce03185a4 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert3.spec @@ -0,0 +1,54 @@ +# Test interaction between concurrent transactions performing +# create and insert in SERIALIZABLE isolation level +# +# Note: +# In this isolation level, it is possible that create_immv could +# create an inconsistent view not including effects of a concurrent +# transaction. So, an warning message is raised to suggest using it +# in READ COMMITTED or executing refresh_immv to make sure to +# make the view contents consistent. + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert.spec b/src/test/isolation/specs/ivm-insert-insert.spec new file mode 100644 index 00000000000..b8f794ca191 --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert2.spec b/src/test/isolation/specs/ivm-insert-insert2.spec new file mode 100644 index 00000000000..ed086d1ba1e --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert2.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in REPEATABLE READ isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert3.spec b/src/test/isolation/specs/ivm-insert-insert3.spec new file mode 100644 index 00000000000..b18bd121033 --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert3.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in SERIALIZABLE isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert.spec b/src/test/isolation/specs/ivm-refresh-insert.spec new file mode 100644 index 00000000000..d7181251962 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert2.spec b/src/test/isolation/specs/ivm-refresh-insert2.spec new file mode 100644 index 00000000000..f2d1d5013f2 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert2.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in REPEATABLE READ isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert3.spec b/src/test/isolation/specs/ivm-refresh-insert3.spec new file mode 100644 index 00000000000..0ec2b1d1de0 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert3.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in SERIALIZABLE isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/regress/expected/incremental_matview.out b/src/test/regress/expected/incremental_matview.out new file mode 100644 index 00000000000..f215aa88e48 --- /dev/null +++ b/src/test/regress/expected/incremental_matview.out @@ -0,0 +1,1100 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ERROR: materialized view "mv_ivm_1" has not been populated +HINT: Use the REFRESH MATERIALIZED VIEW command. +REFRESH MATERIALIZED VIEW mv_ivm_1; +NOTICE: could not create an index on materialized view "mv_ivm_1" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 17 +(1 row) + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 1 +(1 row) + +ROLLBACK; +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_rename_index" on materialized view "mv_ivm_rename" +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +ERROR: IVM column can not be renamed +DROP MATERIALIZED VIEW mv_ivm_rename; +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_unique_index" on materialized view "mv_ivm_unique" +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +ERROR: unique index creation on IVM columns is not supported +DROP MATERIALIZED VIEW mv_ivm_unique; +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +NOTICE: could not create an index on materialized view "mv_ivm_func" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +NOTICE: could not create an index on materialized view "mv_ivm_no_tbl" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_duplicate" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +NOTICE: created index "mv_ivm_distinct_index" on materialized view "mv_ivm_distinct" +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 20 + 30 + 40 + 50 +(6 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +ROLLBACK; +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 120 | 2 | 60.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+---------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 220 | 2 | 110.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 20 | 1 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 120 | 2 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; + sum | count +-----+------- +(0 rows) + +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; + i | sum | count +---+-----+------- +(0 rows) + +ROLLBACK; +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 150 | 5 | 30.0000000000000000 +(1 row) + +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 210 | 6 | 35.0000000000000000 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +NOTICE: created index "mv_ivm_avg_bug_index" on materialized view "mv_ivm_avg_bug" +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 3 | 3.3333333333333333 + 2 | 80 | 3 | 26.6666666666666667 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_min_max_index" on materialized view "mv_ivm_min_max" +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 10 + 2 | 20 | 20 + 3 | 30 | 30 + 4 | 40 | 40 + 5 | 50 | 50 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 12 + 2 | 20 | 22 + 3 | 30 | 32 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 11 | 12 + 2 | 20 | 22 + 3 | 30 | 31 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min_max" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 50 +(1 row) + +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 0 | 70 +(1 row) + +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 60 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + | +(1 row) + +ROLLBACK; +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min; + min +----- + 10 +(1 row) + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + min +----- + 20 +(1 row) + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; + min +----- + 30 +(1 row) + +ROLLBACK; +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | sum +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | b +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ERROR: too many column names were specified +ROLLBACK; +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +NOTICE: could not create an index on materialized view "mv_self" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +----+---- + 10 | 10 + 20 | 20 + 30 | 30 +(3 rows) + +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 30 | 30 + 40 | 40 + 200 | 200 +(3 rows) + +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 130 | 130 + 300 | 300 +(4 rows) + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 70 | 70 + 70 | 77 + 77 | 70 + 77 | 77 + 130 | 130 + 300 | 300 +(8 rows) + +ROLLBACK; +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY v1; + v1 | v2 +----+----- + 10 | 100 + 20 | 200 + 30 | 300 +(3 rows) + +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv ORDER BY v1; + v1 | v2 +------+----- + 10 | 100 + 11 | 100 + 1020 | 200 + 1020 | 222 +(4 rows) + +ROLLBACK; +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +NOTICE: created index "mv_ri_index" on materialized view "mv_ri" +SELECT * FROM mv_ri ORDER BY i1; + i1 | i2 +----+---- + 1 | 1 + 2 | 2 + 3 | 3 +(3 rows) + +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; + i1 | i2 +----+---- + 3 | 3 + 10 | 10 +(2 rows) + +ROLLBACK; +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | +(2 rows) + +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | 20 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i +--- +(0 rows) + +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; + i +--- + 1 + +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 30 + | 3 +(2 rows) + +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 300 + | 30 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 1 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 4 +(1 row) + +ROLLBACK; +-- IMMV containing user defined type +BEGIN; +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: return type mytype is only a shell +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: argument type mytype is only a shell +LINE 1: CREATE FUNCTION mytype_out(mytype) + ^ +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +NOTICE: could not create an index on materialized view "mv_mytype" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + x +--- + 1 +(1 row) + +ROLLBACK; +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +ERROR: OUTER JOIN is not supported on incrementally maintainable materialized view +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +ERROR: CTE is not supported on incrementally maintainable materialized view +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +ERROR: ORDER BY clause is not supported on incrementally maintainable materialized view +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; +ERROR: HAVING clause is not supported on incrementally maintainable materialized view +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; +ERROR: mutable function is not supported on incrementally maintainable materialized view +HINT: functions must be marked IMMUTABLE +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; +ERROR: LIMIT/OFFSET clause is not supported on incrementally maintainable materialized view +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; +ERROR: DISTINCT ON is not supported on incrementally maintainable materialized view +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); +ERROR: TABLESAMPLE clause is not supported on incrementally maintainable materialized view +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; +ERROR: window functions are not supported on incrementally maintainable materialized view +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +ERROR: aggregate function with FILTER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +ERROR: aggregate function with DISTINCT arguments is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +ERROR: aggregate function with ORDER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); +ERROR: GROUPING SETS, ROLLUP, or CUBE clauses is not supported on incrementally maintainable materialized view +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ERROR: inheritance parent is not supported on incrementally maintainable materialized view +ROLLBACK; +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; +ERROR: UNION/INTERSECT/EXCEPT statements are not supported on incrementally maintainable materialized view +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; +ERROR: empty target list is not supported on incrementally maintainable materialized view +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; +ERROR: FOR UPDATE/SHARE clause is not supported on incrementally maintainable materialized view +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; +ERROR: column name __ivm_count__ is not supported on incrementally maintainable materialized view +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; +ERROR: GROUP BY expression not appearing in select list is not supported on incrementally maintainable materialized view +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); +ERROR: VALUES is not supported on incrementally maintainable materialized view +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +NOTICE: role "regress_ivm_admin" does not exist, skipping +DROP USER IF EXISTS regress_ivm_user; +NOTICE: role "regress_ivm_user" does not exist, skipping +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +NOTICE: could not create an index on materialized view "ivm_rls" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user +(1 row) + +RESET SESSION AUTHORIZATION; +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user + 3 | baz | regress_ivm_user +(2 rows) + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +-- +(1 row) + +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+-------+------------------ + 2 | bar | regress_ivm_user + 3 | baz | regress_ivm_user + 6 | corge | regress_ivm_user +(3 rows) + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +NOTICE: could not create an index on materialized view "ivm_rls2" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +RESET SESSION AUTHORIZATION; +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +-- +(1 row) + +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + id | data | owner | num +----+-------+------------------+--------- + 2 | bar | regress_ivm_user | two + 3 | baz_2 | regress_ivm_user | three_2 + 6 | corge | regress_ivm_user | six +(3 rows) + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +NOTICE: could not create an index on materialized view "mv_update_same" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + i +--- + 2 +(1 row) + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +NOTICE: created index "mv_self_ref_index" on materialized view "mv_self_ref" +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; + a | b +----+---- + 11 | + 12 | 11 + 13 | 12 +(3 rows) + +ROLLBACK; +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; +NOTICE: created index "mv_idx1_index" on materialized view "mv_idx1" +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; +NOTICE: created index "mv_idx2_index" on materialized view "mv_idx2" +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; +NOTICE: created index "mv_idx3_index" on materialized view "mv_idx3" +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +NOTICE: could not create an index on materialized view "mv_idx4" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; +NOTICE: could not create an index on materialized view "mv_idx5" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); +NOTICE: could not create an index on materialized view "mv_idx6" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ERROR: data type json has no default operator class for access method "btree" +ROLLBACK; +-- cleanup +DROP TABLE rls_tbl CASCADE; +NOTICE: drop cascades to 2 other objects +DETAIL: drop cascades to materialized view ivm_rls +drop cascades to materialized view ivm_rls2 +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; +DROP TABLE mv_base_b CASCADE; +NOTICE: drop cascades to 3 other objects +DETAIL: drop cascades to materialized view mv_ivm_1 +drop cascades to view b_view +drop cascades to materialized view b_mview +DROP TABLE mv_base_a CASCADE; diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index 8fa0a6c47fb..7caca5f64fd 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -77,6 +77,7 @@ test: brin_bloom brin_multi # Another group of parallel tests # ---------- test: create_table_like alter_generic alter_operator misc async dbsize merge misc_functions nls sysviews tsrf tid tidscan tidrangescan collate.utf8 collate.icu.utf8 incremental_sort create_role without_overlaps generated_virtual +test: incremental_matview # collate.linux.utf8 and collate.icu.utf8 tests cannot be run in parallel with each other # psql depends on create_am diff --git a/src/test/regress/sql/incremental_matview.sql b/src/test/regress/sql/incremental_matview.sql new file mode 100644 index 00000000000..2d55c393d6f --- /dev/null +++ b/src/test/regress/sql/incremental_matview.sql @@ -0,0 +1,580 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); + +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +REFRESH MATERIALIZED VIEW mv_ivm_1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; + +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; +ROLLBACK; + +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +DROP MATERIALIZED VIEW mv_ivm_rename; + +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +DROP MATERIALIZED VIEW mv_ivm_unique; + +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; + + +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +ROLLBACK; + +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +ROLLBACK; + +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +ROLLBACK; + +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +ROLLBACK; + +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +ROLLBACK; + +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min; + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); + +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; +ROLLBACK; + +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +SELECT * FROM mv_self ORDER BY v1; +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; +SELECT * FROM mv_self ORDER BY v1; + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + +ROLLBACK; + +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +SELECT * FROM mv ORDER BY v1; +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; +SELECT * FROM mv ORDER BY v1; +ROLLBACK; + +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +SELECT * FROM mv_ri ORDER BY i1; +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; +ROLLBACK; + +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +-- IMMV containing user defined type +BEGIN; + +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); + +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; + +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); + +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); + +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + +ROLLBACK; + +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; + +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; + +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; + +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; + +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; + +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); + +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; + +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); + +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ROLLBACK; + +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; + +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; + +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; + +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; + +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; + +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; + +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); + +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +DROP USER IF EXISTS regress_ivm_user; +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; + +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); + +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; + +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; + +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; +RESET SESSION AUTHORIZATION; + +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +RESET SESSION AUTHORIZATION; + +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; +ROLLBACK; + +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); + +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; + +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; + +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; + +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; + +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); + +ROLLBACK; + +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ROLLBACK; + +-- cleanup + +DROP TABLE rls_tbl CASCADE; +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; + +DROP TABLE mv_base_b CASCADE; +DROP TABLE mv_base_a CASCADE; -- 2.43.0 --Multipart=_Wed__1_Jul_2026_00_04_01_+0900_OVSy2WWK_9aByzDJ Content-Type: text/x-diff; name="v38-0009-Add-support-for-min-max-aggregates-for-IVM.patch" Content-Disposition: attachment; filename="v38-0009-Add-support-for-min-max-aggregates-for-IVM.patch" Content-Transfer-Encoding: 7bit ^ permalink raw reply [nested|flat] 78+ messages in thread
* [PATCH v38 10/11] Add regression tests for Incremental View Maintenance @ 2026-05-29 09:31 Yugo Nagata <[email protected]> 0 siblings, 0 replies; 78+ messages in thread From: Yugo Nagata @ 2026-05-29 09:31 UTC (permalink / raw) --- .../isolation/expected/ivm-create-insert.out | 285 +++++ .../isolation/expected/ivm-create-insert2.out | 305 +++++ .../isolation/expected/ivm-create-insert3.out | 305 +++++ .../isolation/expected/ivm-insert-insert.out | 497 ++++++++ .../isolation/expected/ivm-insert-insert2.out | 373 ++++++ .../isolation/expected/ivm-insert-insert3.out | 373 ++++++ .../isolation/expected/ivm-refresh-insert.out | 213 ++++ .../expected/ivm-refresh-insert2.out | 191 +++ .../expected/ivm-refresh-insert3.out | 191 +++ src/test/isolation/isolation_schedule | 9 + .../isolation/specs/ivm-create-insert.spec | 47 + .../isolation/specs/ivm-create-insert2.spec | 54 + .../isolation/specs/ivm-create-insert3.spec | 54 + .../isolation/specs/ivm-insert-insert.spec | 62 + .../isolation/specs/ivm-insert-insert2.spec | 62 + .../isolation/specs/ivm-insert-insert3.spec | 62 + .../isolation/specs/ivm-refresh-insert.spec | 46 + .../isolation/specs/ivm-refresh-insert2.spec | 46 + .../isolation/specs/ivm-refresh-insert3.spec | 46 + .../regress/expected/incremental_matview.out | 1100 +++++++++++++++++ src/test/regress/parallel_schedule | 1 + src/test/regress/sql/incremental_matview.sql | 580 +++++++++ 22 files changed, 4902 insertions(+) create mode 100644 src/test/isolation/expected/ivm-create-insert.out create mode 100644 src/test/isolation/expected/ivm-create-insert2.out create mode 100644 src/test/isolation/expected/ivm-create-insert3.out create mode 100644 src/test/isolation/expected/ivm-insert-insert.out create mode 100644 src/test/isolation/expected/ivm-insert-insert2.out create mode 100644 src/test/isolation/expected/ivm-insert-insert3.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert2.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert3.out create mode 100644 src/test/isolation/specs/ivm-create-insert.spec create mode 100644 src/test/isolation/specs/ivm-create-insert2.spec create mode 100644 src/test/isolation/specs/ivm-create-insert3.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert2.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert3.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert2.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert3.spec create mode 100644 src/test/regress/expected/incremental_matview.out create mode 100644 src/test/regress/sql/incremental_matview.sql diff --git a/src/test/isolation/expected/ivm-create-insert.out b/src/test/isolation/expected/ivm-create-insert.out new file mode 100644 index 00000000000..5da00043aba --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert.out @@ -0,0 +1,285 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-create-insert2.out b/src/test/isolation/expected/ivm-create-insert2.out new file mode 100644 index 00000000000..907d892c6d4 --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert2.out @@ -0,0 +1,305 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + diff --git a/src/test/isolation/expected/ivm-create-insert3.out b/src/test/isolation/expected/ivm-create-insert3.out new file mode 100644 index 00000000000..907d892c6d4 --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert3.out @@ -0,0 +1,305 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert.out b/src/test/isolation/expected/ivm-insert-insert.out new file mode 100644 index 00000000000..5ca4cfea677 --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert.out @@ -0,0 +1,497 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; <waiting ...> +step c1: COMMIT; +step update2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; <waiting ...> +step c1: COMMIT; +step update2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; <waiting ...> +step c2: COMMIT; +step update1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; <waiting ...> +step c2: COMMIT; +step update1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); <waiting ...> +step c1: COMMIT; +step insert2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); <waiting ...> +step c1: COMMIT; +step insert2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); <waiting ...> +step c2: COMMIT; +step insert1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); <waiting ...> +step c2: COMMIT; +step insert1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert2.out b/src/test/isolation/expected/ivm-insert-insert2.out new file mode 100644 index 00000000000..e1c66d4de5e --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert2.out @@ -0,0 +1,373 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert3.out b/src/test/isolation/expected/ivm-insert-insert3.out new file mode 100644 index 00000000000..e1c66d4de5e --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert3.out @@ -0,0 +1,373 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert.out b/src/test/isolation/expected/ivm-refresh-insert.out new file mode 100644 index 00000000000..a925938bf1c --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert.out @@ -0,0 +1,213 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert2.out b/src/test/isolation/expected/ivm-refresh-insert2.out new file mode 100644 index 00000000000..dc1b16ae34e --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert2.out @@ -0,0 +1,191 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert3.out b/src/test/isolation/expected/ivm-refresh-insert3.out new file mode 100644 index 00000000000..dc1b16ae34e --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert3.out @@ -0,0 +1,191 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/isolation_schedule b/src/test/isolation/isolation_schedule index b8ebe92553c..6b7e873b370 100644 --- a/src/test/isolation/isolation_schedule +++ b/src/test/isolation/isolation_schedule @@ -128,3 +128,12 @@ test: matview-write-skew test: lock-nowait test: for-portion-of test: ddl-dependency-locking +test: ivm-create-insert +test: ivm-create-insert2 +test: ivm-create-insert3 +test: ivm-insert-insert +test: ivm-insert-insert2 +test: ivm-insert-insert3 +test: ivm-refresh-insert +test: ivm-refresh-insert2 +test: ivm-refresh-insert3 diff --git a/src/test/isolation/specs/ivm-create-insert.spec b/src/test/isolation/specs/ivm-create-insert.spec new file mode 100644 index 00000000000..ccd6fd080a9 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert.spec @@ -0,0 +1,47 @@ +# Test interaction between concurrent transactions performing +# create and insert in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-create-insert2.spec b/src/test/isolation/specs/ivm-create-insert2.spec new file mode 100644 index 00000000000..02cec85ae07 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert2.spec @@ -0,0 +1,54 @@ +# Test interaction between concurrent transactions performing +# create and insert in REPEATABLE READ isolation level +# +# Note: +# In this isolation level, it is possible that create_immv could +# create an inconsistent view not including effects of a concurrent +# transaction. So, an warning message is raised to suggest using it +# in READ COMMITTED or executing refresh_immv to make sure to +# make the view contents consistent. + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-create-insert3.spec b/src/test/isolation/specs/ivm-create-insert3.spec new file mode 100644 index 00000000000..19ce03185a4 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert3.spec @@ -0,0 +1,54 @@ +# Test interaction between concurrent transactions performing +# create and insert in SERIALIZABLE isolation level +# +# Note: +# In this isolation level, it is possible that create_immv could +# create an inconsistent view not including effects of a concurrent +# transaction. So, an warning message is raised to suggest using it +# in READ COMMITTED or executing refresh_immv to make sure to +# make the view contents consistent. + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert.spec b/src/test/isolation/specs/ivm-insert-insert.spec new file mode 100644 index 00000000000..b8f794ca191 --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert2.spec b/src/test/isolation/specs/ivm-insert-insert2.spec new file mode 100644 index 00000000000..ed086d1ba1e --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert2.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in REPEATABLE READ isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert3.spec b/src/test/isolation/specs/ivm-insert-insert3.spec new file mode 100644 index 00000000000..b18bd121033 --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert3.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in SERIALIZABLE isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert.spec b/src/test/isolation/specs/ivm-refresh-insert.spec new file mode 100644 index 00000000000..d7181251962 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert2.spec b/src/test/isolation/specs/ivm-refresh-insert2.spec new file mode 100644 index 00000000000..f2d1d5013f2 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert2.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in REPEATABLE READ isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert3.spec b/src/test/isolation/specs/ivm-refresh-insert3.spec new file mode 100644 index 00000000000..0ec2b1d1de0 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert3.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in SERIALIZABLE isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/regress/expected/incremental_matview.out b/src/test/regress/expected/incremental_matview.out new file mode 100644 index 00000000000..f215aa88e48 --- /dev/null +++ b/src/test/regress/expected/incremental_matview.out @@ -0,0 +1,1100 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ERROR: materialized view "mv_ivm_1" has not been populated +HINT: Use the REFRESH MATERIALIZED VIEW command. +REFRESH MATERIALIZED VIEW mv_ivm_1; +NOTICE: could not create an index on materialized view "mv_ivm_1" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 17 +(1 row) + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 1 +(1 row) + +ROLLBACK; +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_rename_index" on materialized view "mv_ivm_rename" +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +ERROR: IVM column can not be renamed +DROP MATERIALIZED VIEW mv_ivm_rename; +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_unique_index" on materialized view "mv_ivm_unique" +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +ERROR: unique index creation on IVM columns is not supported +DROP MATERIALIZED VIEW mv_ivm_unique; +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +NOTICE: could not create an index on materialized view "mv_ivm_func" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +NOTICE: could not create an index on materialized view "mv_ivm_no_tbl" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_duplicate" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +NOTICE: created index "mv_ivm_distinct_index" on materialized view "mv_ivm_distinct" +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 20 + 30 + 40 + 50 +(6 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +ROLLBACK; +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 120 | 2 | 60.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+---------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 220 | 2 | 110.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 20 | 1 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 120 | 2 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; + sum | count +-----+------- +(0 rows) + +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; + i | sum | count +---+-----+------- +(0 rows) + +ROLLBACK; +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 150 | 5 | 30.0000000000000000 +(1 row) + +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 210 | 6 | 35.0000000000000000 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +NOTICE: created index "mv_ivm_avg_bug_index" on materialized view "mv_ivm_avg_bug" +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 3 | 3.3333333333333333 + 2 | 80 | 3 | 26.6666666666666667 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_min_max_index" on materialized view "mv_ivm_min_max" +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 10 + 2 | 20 | 20 + 3 | 30 | 30 + 4 | 40 | 40 + 5 | 50 | 50 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 12 + 2 | 20 | 22 + 3 | 30 | 32 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 11 | 12 + 2 | 20 | 22 + 3 | 30 | 31 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min_max" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 50 +(1 row) + +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 0 | 70 +(1 row) + +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 60 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + | +(1 row) + +ROLLBACK; +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min; + min +----- + 10 +(1 row) + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + min +----- + 20 +(1 row) + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; + min +----- + 30 +(1 row) + +ROLLBACK; +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | sum +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | b +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ERROR: too many column names were specified +ROLLBACK; +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +NOTICE: could not create an index on materialized view "mv_self" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +----+---- + 10 | 10 + 20 | 20 + 30 | 30 +(3 rows) + +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 30 | 30 + 40 | 40 + 200 | 200 +(3 rows) + +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 130 | 130 + 300 | 300 +(4 rows) + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 70 | 70 + 70 | 77 + 77 | 70 + 77 | 77 + 130 | 130 + 300 | 300 +(8 rows) + +ROLLBACK; +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY v1; + v1 | v2 +----+----- + 10 | 100 + 20 | 200 + 30 | 300 +(3 rows) + +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv ORDER BY v1; + v1 | v2 +------+----- + 10 | 100 + 11 | 100 + 1020 | 200 + 1020 | 222 +(4 rows) + +ROLLBACK; +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +NOTICE: created index "mv_ri_index" on materialized view "mv_ri" +SELECT * FROM mv_ri ORDER BY i1; + i1 | i2 +----+---- + 1 | 1 + 2 | 2 + 3 | 3 +(3 rows) + +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; + i1 | i2 +----+---- + 3 | 3 + 10 | 10 +(2 rows) + +ROLLBACK; +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | +(2 rows) + +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | 20 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i +--- +(0 rows) + +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; + i +--- + 1 + +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 30 + | 3 +(2 rows) + +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 300 + | 30 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 1 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 4 +(1 row) + +ROLLBACK; +-- IMMV containing user defined type +BEGIN; +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: return type mytype is only a shell +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: argument type mytype is only a shell +LINE 1: CREATE FUNCTION mytype_out(mytype) + ^ +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +NOTICE: could not create an index on materialized view "mv_mytype" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + x +--- + 1 +(1 row) + +ROLLBACK; +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +ERROR: OUTER JOIN is not supported on incrementally maintainable materialized view +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +ERROR: CTE is not supported on incrementally maintainable materialized view +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +ERROR: ORDER BY clause is not supported on incrementally maintainable materialized view +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; +ERROR: HAVING clause is not supported on incrementally maintainable materialized view +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; +ERROR: mutable function is not supported on incrementally maintainable materialized view +HINT: functions must be marked IMMUTABLE +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; +ERROR: LIMIT/OFFSET clause is not supported on incrementally maintainable materialized view +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; +ERROR: DISTINCT ON is not supported on incrementally maintainable materialized view +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); +ERROR: TABLESAMPLE clause is not supported on incrementally maintainable materialized view +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; +ERROR: window functions are not supported on incrementally maintainable materialized view +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +ERROR: aggregate function with FILTER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +ERROR: aggregate function with DISTINCT arguments is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +ERROR: aggregate function with ORDER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); +ERROR: GROUPING SETS, ROLLUP, or CUBE clauses is not supported on incrementally maintainable materialized view +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ERROR: inheritance parent is not supported on incrementally maintainable materialized view +ROLLBACK; +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; +ERROR: UNION/INTERSECT/EXCEPT statements are not supported on incrementally maintainable materialized view +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; +ERROR: empty target list is not supported on incrementally maintainable materialized view +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; +ERROR: FOR UPDATE/SHARE clause is not supported on incrementally maintainable materialized view +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; +ERROR: column name __ivm_count__ is not supported on incrementally maintainable materialized view +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; +ERROR: GROUP BY expression not appearing in select list is not supported on incrementally maintainable materialized view +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); +ERROR: VALUES is not supported on incrementally maintainable materialized view +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +NOTICE: role "regress_ivm_admin" does not exist, skipping +DROP USER IF EXISTS regress_ivm_user; +NOTICE: role "regress_ivm_user" does not exist, skipping +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +NOTICE: could not create an index on materialized view "ivm_rls" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user +(1 row) + +RESET SESSION AUTHORIZATION; +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user + 3 | baz | regress_ivm_user +(2 rows) + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +-- +(1 row) + +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+-------+------------------ + 2 | bar | regress_ivm_user + 3 | baz | regress_ivm_user + 6 | corge | regress_ivm_user +(3 rows) + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +NOTICE: could not create an index on materialized view "ivm_rls2" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +RESET SESSION AUTHORIZATION; +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +-- +(1 row) + +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + id | data | owner | num +----+-------+------------------+--------- + 2 | bar | regress_ivm_user | two + 3 | baz_2 | regress_ivm_user | three_2 + 6 | corge | regress_ivm_user | six +(3 rows) + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +NOTICE: could not create an index on materialized view "mv_update_same" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + i +--- + 2 +(1 row) + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +NOTICE: created index "mv_self_ref_index" on materialized view "mv_self_ref" +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; + a | b +----+---- + 11 | + 12 | 11 + 13 | 12 +(3 rows) + +ROLLBACK; +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; +NOTICE: created index "mv_idx1_index" on materialized view "mv_idx1" +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; +NOTICE: created index "mv_idx2_index" on materialized view "mv_idx2" +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; +NOTICE: created index "mv_idx3_index" on materialized view "mv_idx3" +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +NOTICE: could not create an index on materialized view "mv_idx4" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; +NOTICE: could not create an index on materialized view "mv_idx5" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); +NOTICE: could not create an index on materialized view "mv_idx6" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ERROR: data type json has no default operator class for access method "btree" +ROLLBACK; +-- cleanup +DROP TABLE rls_tbl CASCADE; +NOTICE: drop cascades to 2 other objects +DETAIL: drop cascades to materialized view ivm_rls +drop cascades to materialized view ivm_rls2 +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; +DROP TABLE mv_base_b CASCADE; +NOTICE: drop cascades to 3 other objects +DETAIL: drop cascades to materialized view mv_ivm_1 +drop cascades to view b_view +drop cascades to materialized view b_mview +DROP TABLE mv_base_a CASCADE; diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index 8fa0a6c47fb..7caca5f64fd 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -77,6 +77,7 @@ test: brin_bloom brin_multi # Another group of parallel tests # ---------- test: create_table_like alter_generic alter_operator misc async dbsize merge misc_functions nls sysviews tsrf tid tidscan tidrangescan collate.utf8 collate.icu.utf8 incremental_sort create_role without_overlaps generated_virtual +test: incremental_matview # collate.linux.utf8 and collate.icu.utf8 tests cannot be run in parallel with each other # psql depends on create_am diff --git a/src/test/regress/sql/incremental_matview.sql b/src/test/regress/sql/incremental_matview.sql new file mode 100644 index 00000000000..2d55c393d6f --- /dev/null +++ b/src/test/regress/sql/incremental_matview.sql @@ -0,0 +1,580 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); + +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +REFRESH MATERIALIZED VIEW mv_ivm_1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; + +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; +ROLLBACK; + +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +DROP MATERIALIZED VIEW mv_ivm_rename; + +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +DROP MATERIALIZED VIEW mv_ivm_unique; + +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; + + +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +ROLLBACK; + +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +ROLLBACK; + +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +ROLLBACK; + +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +ROLLBACK; + +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +ROLLBACK; + +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min; + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); + +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; +ROLLBACK; + +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +SELECT * FROM mv_self ORDER BY v1; +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; +SELECT * FROM mv_self ORDER BY v1; + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + +ROLLBACK; + +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +SELECT * FROM mv ORDER BY v1; +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; +SELECT * FROM mv ORDER BY v1; +ROLLBACK; + +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +SELECT * FROM mv_ri ORDER BY i1; +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; +ROLLBACK; + +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +-- IMMV containing user defined type +BEGIN; + +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); + +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; + +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); + +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); + +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + +ROLLBACK; + +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; + +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; + +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; + +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; + +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; + +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); + +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; + +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); + +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ROLLBACK; + +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; + +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; + +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; + +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; + +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; + +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; + +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); + +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +DROP USER IF EXISTS regress_ivm_user; +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; + +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); + +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; + +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; + +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; +RESET SESSION AUTHORIZATION; + +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +RESET SESSION AUTHORIZATION; + +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; +ROLLBACK; + +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); + +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; + +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; + +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; + +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; + +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); + +ROLLBACK; + +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ROLLBACK; + +-- cleanup + +DROP TABLE rls_tbl CASCADE; +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; + +DROP TABLE mv_base_b CASCADE; +DROP TABLE mv_base_a CASCADE; -- 2.43.0 --Multipart=_Wed__1_Jul_2026_00_04_01_+0900_OVSy2WWK_9aByzDJ Content-Type: text/x-diff; name="v38-0009-Add-support-for-min-max-aggregates-for-IVM.patch" Content-Disposition: attachment; filename="v38-0009-Add-support-for-min-max-aggregates-for-IVM.patch" Content-Transfer-Encoding: 7bit ^ permalink raw reply [nested|flat] 78+ messages in thread
* [PATCH v39 7/8] Add regression tests for Incremental View Maintenance @ 2026-05-29 09:31 Yugo Nagata <[email protected]> 0 siblings, 0 replies; 78+ messages in thread From: Yugo Nagata @ 2026-05-29 09:31 UTC (permalink / raw) --- .../isolation/expected/ivm-create-insert.out | 285 ++++++++ .../isolation/expected/ivm-create-insert2.out | 305 ++++++++ .../isolation/expected/ivm-create-insert3.out | 305 ++++++++ .../isolation/expected/ivm-insert-insert.out | 497 +++++++++++++ .../isolation/expected/ivm-insert-insert2.out | 373 ++++++++++ .../isolation/expected/ivm-insert-insert3.out | 373 ++++++++++ .../isolation/expected/ivm-refresh-insert.out | 213 ++++++ .../expected/ivm-refresh-insert2.out | 191 +++++ .../expected/ivm-refresh-insert3.out | 191 +++++ src/test/isolation/isolation_schedule | 9 + .../isolation/specs/ivm-create-insert.spec | 47 ++ .../isolation/specs/ivm-create-insert2.spec | 54 ++ .../isolation/specs/ivm-create-insert3.spec | 54 ++ .../isolation/specs/ivm-insert-insert.spec | 62 ++ .../isolation/specs/ivm-insert-insert2.spec | 62 ++ .../isolation/specs/ivm-insert-insert3.spec | 62 ++ .../isolation/specs/ivm-refresh-insert.spec | 46 ++ .../isolation/specs/ivm-refresh-insert2.spec | 46 ++ .../isolation/specs/ivm-refresh-insert3.spec | 46 ++ .../regress/expected/incremental_matview.out | 667 ++++++++++++++++++ src/test/regress/parallel_schedule | 1 + src/test/regress/sql/incremental_matview.sql | 407 +++++++++++ 22 files changed, 4296 insertions(+) create mode 100644 src/test/isolation/expected/ivm-create-insert.out create mode 100644 src/test/isolation/expected/ivm-create-insert2.out create mode 100644 src/test/isolation/expected/ivm-create-insert3.out create mode 100644 src/test/isolation/expected/ivm-insert-insert.out create mode 100644 src/test/isolation/expected/ivm-insert-insert2.out create mode 100644 src/test/isolation/expected/ivm-insert-insert3.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert2.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert3.out create mode 100644 src/test/isolation/specs/ivm-create-insert.spec create mode 100644 src/test/isolation/specs/ivm-create-insert2.spec create mode 100644 src/test/isolation/specs/ivm-create-insert3.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert2.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert3.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert2.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert3.spec create mode 100644 src/test/regress/expected/incremental_matview.out create mode 100644 src/test/regress/sql/incremental_matview.sql diff --git a/src/test/isolation/expected/ivm-create-insert.out b/src/test/isolation/expected/ivm-create-insert.out new file mode 100644 index 00000000000..5da00043aba --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert.out @@ -0,0 +1,285 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-create-insert2.out b/src/test/isolation/expected/ivm-create-insert2.out new file mode 100644 index 00000000000..907d892c6d4 --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert2.out @@ -0,0 +1,305 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + diff --git a/src/test/isolation/expected/ivm-create-insert3.out b/src/test/isolation/expected/ivm-create-insert3.out new file mode 100644 index 00000000000..907d892c6d4 --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert3.out @@ -0,0 +1,305 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert.out b/src/test/isolation/expected/ivm-insert-insert.out new file mode 100644 index 00000000000..5ca4cfea677 --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert.out @@ -0,0 +1,497 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; <waiting ...> +step c1: COMMIT; +step update2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; <waiting ...> +step c1: COMMIT; +step update2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; <waiting ...> +step c2: COMMIT; +step update1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; <waiting ...> +step c2: COMMIT; +step update1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); <waiting ...> +step c1: COMMIT; +step insert2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); <waiting ...> +step c1: COMMIT; +step insert2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); <waiting ...> +step c2: COMMIT; +step insert1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); <waiting ...> +step c2: COMMIT; +step insert1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert2.out b/src/test/isolation/expected/ivm-insert-insert2.out new file mode 100644 index 00000000000..e1c66d4de5e --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert2.out @@ -0,0 +1,373 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert3.out b/src/test/isolation/expected/ivm-insert-insert3.out new file mode 100644 index 00000000000..e1c66d4de5e --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert3.out @@ -0,0 +1,373 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert.out b/src/test/isolation/expected/ivm-refresh-insert.out new file mode 100644 index 00000000000..a925938bf1c --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert.out @@ -0,0 +1,213 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert2.out b/src/test/isolation/expected/ivm-refresh-insert2.out new file mode 100644 index 00000000000..dc1b16ae34e --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert2.out @@ -0,0 +1,191 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert3.out b/src/test/isolation/expected/ivm-refresh-insert3.out new file mode 100644 index 00000000000..dc1b16ae34e --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert3.out @@ -0,0 +1,191 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/isolation_schedule b/src/test/isolation/isolation_schedule index b8ebe92553c..6b7e873b370 100644 --- a/src/test/isolation/isolation_schedule +++ b/src/test/isolation/isolation_schedule @@ -128,3 +128,12 @@ test: matview-write-skew test: lock-nowait test: for-portion-of test: ddl-dependency-locking +test: ivm-create-insert +test: ivm-create-insert2 +test: ivm-create-insert3 +test: ivm-insert-insert +test: ivm-insert-insert2 +test: ivm-insert-insert3 +test: ivm-refresh-insert +test: ivm-refresh-insert2 +test: ivm-refresh-insert3 diff --git a/src/test/isolation/specs/ivm-create-insert.spec b/src/test/isolation/specs/ivm-create-insert.spec new file mode 100644 index 00000000000..ccd6fd080a9 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert.spec @@ -0,0 +1,47 @@ +# Test interaction between concurrent transactions performing +# create and insert in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-create-insert2.spec b/src/test/isolation/specs/ivm-create-insert2.spec new file mode 100644 index 00000000000..02cec85ae07 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert2.spec @@ -0,0 +1,54 @@ +# Test interaction between concurrent transactions performing +# create and insert in REPEATABLE READ isolation level +# +# Note: +# In this isolation level, it is possible that create_immv could +# create an inconsistent view not including effects of a concurrent +# transaction. So, an warning message is raised to suggest using it +# in READ COMMITTED or executing refresh_immv to make sure to +# make the view contents consistent. + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-create-insert3.spec b/src/test/isolation/specs/ivm-create-insert3.spec new file mode 100644 index 00000000000..19ce03185a4 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert3.spec @@ -0,0 +1,54 @@ +# Test interaction between concurrent transactions performing +# create and insert in SERIALIZABLE isolation level +# +# Note: +# In this isolation level, it is possible that create_immv could +# create an inconsistent view not including effects of a concurrent +# transaction. So, an warning message is raised to suggest using it +# in READ COMMITTED or executing refresh_immv to make sure to +# make the view contents consistent. + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert.spec b/src/test/isolation/specs/ivm-insert-insert.spec new file mode 100644 index 00000000000..b8f794ca191 --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert2.spec b/src/test/isolation/specs/ivm-insert-insert2.spec new file mode 100644 index 00000000000..ed086d1ba1e --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert2.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in REPEATABLE READ isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert3.spec b/src/test/isolation/specs/ivm-insert-insert3.spec new file mode 100644 index 00000000000..b18bd121033 --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert3.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in SERIALIZABLE isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert.spec b/src/test/isolation/specs/ivm-refresh-insert.spec new file mode 100644 index 00000000000..d7181251962 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert2.spec b/src/test/isolation/specs/ivm-refresh-insert2.spec new file mode 100644 index 00000000000..f2d1d5013f2 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert2.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in REPEATABLE READ isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert3.spec b/src/test/isolation/specs/ivm-refresh-insert3.spec new file mode 100644 index 00000000000..0ec2b1d1de0 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert3.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in SERIALIZABLE isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/regress/expected/incremental_matview.out b/src/test/regress/expected/incremental_matview.out new file mode 100644 index 00000000000..c7fd19fdca3 --- /dev/null +++ b/src/test/regress/expected/incremental_matview.out @@ -0,0 +1,667 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ERROR: materialized view "mv_ivm_1" has not been populated +HINT: Use the REFRESH MATERIALIZED VIEW command. +REFRESH MATERIALIZED VIEW mv_ivm_1; +NOTICE: could not create an index on materialized view "mv_ivm_1" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 17 +(1 row) + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 1 +(1 row) + +ROLLBACK; +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- DISTINCT not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT * FROM mv_base_a; +ERROR: DISTINCT is not supported on incrementally maintainable materialized view +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +NOTICE: could not create an index on materialized view "mv_ivm_func" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +NOTICE: could not create an index on materialized view "mv_ivm_no_tbl" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- result of materialized view have duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_duplicate" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 20 + 30 + 40 + 50 +(6 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +ROLLBACK; +-- aggregate not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +ERROR: aggregate function is not supported on incrementally maintainable materialized view +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +NOTICE: could not create an index on materialized view "mv_self" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +----+---- + 10 | 10 + 20 | 20 + 30 | 30 +(3 rows) + +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 30 | 30 + 40 | 40 + 200 | 200 +(3 rows) + +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 130 | 130 + 300 | 300 +(4 rows) + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 70 | 70 + 70 | 77 + 77 | 70 + 77 | 77 + 130 | 130 + 300 | 300 +(8 rows) + +ROLLBACK; +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY v1; + v1 | v2 +----+----- + 10 | 100 + 20 | 200 + 30 | 300 +(3 rows) + +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv ORDER BY v1; + v1 | v2 +------+----- + 10 | 100 + 11 | 100 + 1020 | 200 + 1020 | 222 +(4 rows) + +ROLLBACK; +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +NOTICE: created index "mv_ri_index" on materialized view "mv_ri" +SELECT * FROM mv_ri ORDER BY i1; + i1 | i2 +----+---- + 1 | 1 + 2 | 2 + 3 | 3 +(3 rows) + +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; + i1 | i2 +----+---- + 3 | 3 + 10 | 10 +(2 rows) + +ROLLBACK; +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | +(2 rows) + +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | 20 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i +--- +(0 rows) + +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; + i +--- + 1 + +(2 rows) + +ROLLBACK; +-- IMMV containing user defined type +BEGIN; +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: return type mytype is only a shell +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: argument type mytype is only a shell +LINE 1: CREATE FUNCTION mytype_out(mytype) + ^ +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +NOTICE: could not create an index on materialized view "mv_mytype" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + x +--- + 1 +(1 row) + +ROLLBACK; +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +ERROR: OUTER JOIN is not supported on incrementally maintainable materialized view +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +ERROR: CTE is not supported on incrementally maintainable materialized view +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +ERROR: ORDER BY clause is not supported on incrementally maintainable materialized view +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; +ERROR: HAVING clause is not supported on incrementally maintainable materialized view +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; +ERROR: mutable function is not supported on incrementally maintainable materialized view +HINT: functions must be marked IMMUTABLE +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; +ERROR: LIMIT/OFFSET clause is not supported on incrementally maintainable materialized view +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; +ERROR: DISTINCT is not supported on incrementally maintainable materialized view +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); +ERROR: TABLESAMPLE clause is not supported on incrementally maintainable materialized view +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; +ERROR: window functions are not supported on incrementally maintainable materialized view +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ERROR: inheritance parent is not supported on incrementally maintainable materialized view +ROLLBACK; +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; +ERROR: UNION/INTERSECT/EXCEPT statements are not supported on incrementally maintainable materialized view +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; +ERROR: empty target list is not supported on incrementally maintainable materialized view +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; +ERROR: FOR UPDATE/SHARE clause is not supported on incrementally maintainable materialized view +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; +ERROR: column name __ivm_count__ is not supported on incrementally maintainable materialized view +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; +ERROR: aggregate function is not supported on incrementally maintainable materialized view +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); +ERROR: VALUES is not supported on incrementally maintainable materialized view +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +NOTICE: role "regress_ivm_admin" does not exist, skipping +DROP USER IF EXISTS regress_ivm_user; +NOTICE: role "regress_ivm_user" does not exist, skipping +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +NOTICE: could not create an index on materialized view "ivm_rls" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user +(1 row) + +RESET SESSION AUTHORIZATION; +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user + 3 | baz | regress_ivm_user +(2 rows) + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +-- +(1 row) + +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+-------+------------------ + 2 | bar | regress_ivm_user + 3 | baz | regress_ivm_user + 6 | corge | regress_ivm_user +(3 rows) + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +NOTICE: could not create an index on materialized view "ivm_rls2" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +RESET SESSION AUTHORIZATION; +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +-- +(1 row) + +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + id | data | owner | num +----+-------+------------------+--------- + 2 | bar | regress_ivm_user | two + 3 | baz_2 | regress_ivm_user | three_2 + 6 | corge | regress_ivm_user | six +(3 rows) + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +NOTICE: could not create an index on materialized view "mv_update_same" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + i +--- + 2 +(1 row) + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +NOTICE: created index "mv_self_ref_index" on materialized view "mv_self_ref" +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; + a | b +----+---- + 11 | + 12 | 11 + 13 | 12 +(3 rows) + +ROLLBACK; +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; +NOTICE: created index "mv_idx3_index" on materialized view "mv_idx3" +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +NOTICE: could not create an index on materialized view "mv_idx4" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; +NOTICE: could not create an index on materialized view "mv_idx5" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); +NOTICE: could not create an index on materialized view "mv_idx6" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ERROR: data type json has no default operator class for access method "btree" +ROLLBACK; +-- cleanup +DROP TABLE rls_tbl CASCADE; +NOTICE: drop cascades to 2 other objects +DETAIL: drop cascades to materialized view ivm_rls +drop cascades to materialized view ivm_rls2 +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; +DROP TABLE mv_base_b CASCADE; +NOTICE: drop cascades to 3 other objects +DETAIL: drop cascades to materialized view mv_ivm_1 +drop cascades to view b_view +drop cascades to materialized view b_mview +DROP TABLE mv_base_a CASCADE; diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index 8fa0a6c47fb..7caca5f64fd 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -77,6 +77,7 @@ test: brin_bloom brin_multi # Another group of parallel tests # ---------- test: create_table_like alter_generic alter_operator misc async dbsize merge misc_functions nls sysviews tsrf tid tidscan tidrangescan collate.utf8 collate.icu.utf8 incremental_sort create_role without_overlaps generated_virtual +test: incremental_matview # collate.linux.utf8 and collate.icu.utf8 tests cannot be run in parallel with each other # psql depends on create_am diff --git a/src/test/regress/sql/incremental_matview.sql b/src/test/regress/sql/incremental_matview.sql new file mode 100644 index 00000000000..7313ad82f3e --- /dev/null +++ b/src/test/regress/sql/incremental_matview.sql @@ -0,0 +1,407 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); + +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +REFRESH MATERIALIZED VIEW mv_ivm_1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; + +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; +ROLLBACK; + +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- DISTINCT not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT * FROM mv_base_a; + +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; + + +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +ROLLBACK; + +-- result of materialized view have duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +ROLLBACK; + +-- aggregate not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; + +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +SELECT * FROM mv_self ORDER BY v1; +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; +SELECT * FROM mv_self ORDER BY v1; + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + +ROLLBACK; + +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +SELECT * FROM mv ORDER BY v1; +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; +SELECT * FROM mv ORDER BY v1; +ROLLBACK; + +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +SELECT * FROM mv_ri ORDER BY i1; +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; +ROLLBACK; + +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +-- IMMV containing user defined type +BEGIN; + +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); + +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; + +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); + +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); + +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + +ROLLBACK; + +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; + +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; + +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; + +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; + +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; + +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); + +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; + +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ROLLBACK; + +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; + +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; + +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; + +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; + +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; + +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); + +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +DROP USER IF EXISTS regress_ivm_user; +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; + +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); + +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; + +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; + +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; +RESET SESSION AUTHORIZATION; + +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +RESET SESSION AUTHORIZATION; + +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; +ROLLBACK; + +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); + +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; + +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; + +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); + +ROLLBACK; + +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ROLLBACK; + +-- cleanup + +DROP TABLE rls_tbl CASCADE; +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; + +DROP TABLE mv_base_b CASCADE; +DROP TABLE mv_base_a CASCADE; -- 2.43.0 --Multipart=_Fri__3_Jul_2026_19_11_16_+0900_CskxSIu_iGcDMEyM Content-Type: text/x-diff; name="v39-0006-Add-Incremental-View-Maintenance-support.patch" Content-Disposition: attachment; filename="v39-0006-Add-Incremental-View-Maintenance-support.patch" Content-Transfer-Encoding: 7bit ^ permalink raw reply [nested|flat] 78+ messages in thread
* [PATCH v38 10/11] Add regression tests for Incremental View Maintenance @ 2026-05-29 09:31 Yugo Nagata <[email protected]> 0 siblings, 0 replies; 78+ messages in thread From: Yugo Nagata @ 2026-05-29 09:31 UTC (permalink / raw) --- .../isolation/expected/ivm-create-insert.out | 285 +++++ .../isolation/expected/ivm-create-insert2.out | 305 +++++ .../isolation/expected/ivm-create-insert3.out | 305 +++++ .../isolation/expected/ivm-insert-insert.out | 497 ++++++++ .../isolation/expected/ivm-insert-insert2.out | 373 ++++++ .../isolation/expected/ivm-insert-insert3.out | 373 ++++++ .../isolation/expected/ivm-refresh-insert.out | 213 ++++ .../expected/ivm-refresh-insert2.out | 191 +++ .../expected/ivm-refresh-insert3.out | 191 +++ src/test/isolation/isolation_schedule | 9 + .../isolation/specs/ivm-create-insert.spec | 47 + .../isolation/specs/ivm-create-insert2.spec | 54 + .../isolation/specs/ivm-create-insert3.spec | 54 + .../isolation/specs/ivm-insert-insert.spec | 62 + .../isolation/specs/ivm-insert-insert2.spec | 62 + .../isolation/specs/ivm-insert-insert3.spec | 62 + .../isolation/specs/ivm-refresh-insert.spec | 46 + .../isolation/specs/ivm-refresh-insert2.spec | 46 + .../isolation/specs/ivm-refresh-insert3.spec | 46 + .../regress/expected/incremental_matview.out | 1100 +++++++++++++++++ src/test/regress/parallel_schedule | 1 + src/test/regress/sql/incremental_matview.sql | 580 +++++++++ 22 files changed, 4902 insertions(+) create mode 100644 src/test/isolation/expected/ivm-create-insert.out create mode 100644 src/test/isolation/expected/ivm-create-insert2.out create mode 100644 src/test/isolation/expected/ivm-create-insert3.out create mode 100644 src/test/isolation/expected/ivm-insert-insert.out create mode 100644 src/test/isolation/expected/ivm-insert-insert2.out create mode 100644 src/test/isolation/expected/ivm-insert-insert3.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert2.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert3.out create mode 100644 src/test/isolation/specs/ivm-create-insert.spec create mode 100644 src/test/isolation/specs/ivm-create-insert2.spec create mode 100644 src/test/isolation/specs/ivm-create-insert3.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert2.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert3.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert2.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert3.spec create mode 100644 src/test/regress/expected/incremental_matview.out create mode 100644 src/test/regress/sql/incremental_matview.sql diff --git a/src/test/isolation/expected/ivm-create-insert.out b/src/test/isolation/expected/ivm-create-insert.out new file mode 100644 index 00000000000..5da00043aba --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert.out @@ -0,0 +1,285 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-create-insert2.out b/src/test/isolation/expected/ivm-create-insert2.out new file mode 100644 index 00000000000..907d892c6d4 --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert2.out @@ -0,0 +1,305 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + diff --git a/src/test/isolation/expected/ivm-create-insert3.out b/src/test/isolation/expected/ivm-create-insert3.out new file mode 100644 index 00000000000..907d892c6d4 --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert3.out @@ -0,0 +1,305 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert.out b/src/test/isolation/expected/ivm-insert-insert.out new file mode 100644 index 00000000000..5ca4cfea677 --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert.out @@ -0,0 +1,497 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; <waiting ...> +step c1: COMMIT; +step update2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; <waiting ...> +step c1: COMMIT; +step update2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; <waiting ...> +step c2: COMMIT; +step update1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; <waiting ...> +step c2: COMMIT; +step update1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); <waiting ...> +step c1: COMMIT; +step insert2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); <waiting ...> +step c1: COMMIT; +step insert2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); <waiting ...> +step c2: COMMIT; +step insert1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); <waiting ...> +step c2: COMMIT; +step insert1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert2.out b/src/test/isolation/expected/ivm-insert-insert2.out new file mode 100644 index 00000000000..e1c66d4de5e --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert2.out @@ -0,0 +1,373 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert3.out b/src/test/isolation/expected/ivm-insert-insert3.out new file mode 100644 index 00000000000..e1c66d4de5e --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert3.out @@ -0,0 +1,373 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert.out b/src/test/isolation/expected/ivm-refresh-insert.out new file mode 100644 index 00000000000..a925938bf1c --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert.out @@ -0,0 +1,213 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert2.out b/src/test/isolation/expected/ivm-refresh-insert2.out new file mode 100644 index 00000000000..dc1b16ae34e --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert2.out @@ -0,0 +1,191 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert3.out b/src/test/isolation/expected/ivm-refresh-insert3.out new file mode 100644 index 00000000000..dc1b16ae34e --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert3.out @@ -0,0 +1,191 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/isolation_schedule b/src/test/isolation/isolation_schedule index b8ebe92553c..6b7e873b370 100644 --- a/src/test/isolation/isolation_schedule +++ b/src/test/isolation/isolation_schedule @@ -128,3 +128,12 @@ test: matview-write-skew test: lock-nowait test: for-portion-of test: ddl-dependency-locking +test: ivm-create-insert +test: ivm-create-insert2 +test: ivm-create-insert3 +test: ivm-insert-insert +test: ivm-insert-insert2 +test: ivm-insert-insert3 +test: ivm-refresh-insert +test: ivm-refresh-insert2 +test: ivm-refresh-insert3 diff --git a/src/test/isolation/specs/ivm-create-insert.spec b/src/test/isolation/specs/ivm-create-insert.spec new file mode 100644 index 00000000000..ccd6fd080a9 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert.spec @@ -0,0 +1,47 @@ +# Test interaction between concurrent transactions performing +# create and insert in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-create-insert2.spec b/src/test/isolation/specs/ivm-create-insert2.spec new file mode 100644 index 00000000000..02cec85ae07 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert2.spec @@ -0,0 +1,54 @@ +# Test interaction between concurrent transactions performing +# create and insert in REPEATABLE READ isolation level +# +# Note: +# In this isolation level, it is possible that create_immv could +# create an inconsistent view not including effects of a concurrent +# transaction. So, an warning message is raised to suggest using it +# in READ COMMITTED or executing refresh_immv to make sure to +# make the view contents consistent. + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-create-insert3.spec b/src/test/isolation/specs/ivm-create-insert3.spec new file mode 100644 index 00000000000..19ce03185a4 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert3.spec @@ -0,0 +1,54 @@ +# Test interaction between concurrent transactions performing +# create and insert in SERIALIZABLE isolation level +# +# Note: +# In this isolation level, it is possible that create_immv could +# create an inconsistent view not including effects of a concurrent +# transaction. So, an warning message is raised to suggest using it +# in READ COMMITTED or executing refresh_immv to make sure to +# make the view contents consistent. + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert.spec b/src/test/isolation/specs/ivm-insert-insert.spec new file mode 100644 index 00000000000..b8f794ca191 --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert2.spec b/src/test/isolation/specs/ivm-insert-insert2.spec new file mode 100644 index 00000000000..ed086d1ba1e --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert2.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in REPEATABLE READ isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert3.spec b/src/test/isolation/specs/ivm-insert-insert3.spec new file mode 100644 index 00000000000..b18bd121033 --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert3.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in SERIALIZABLE isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert.spec b/src/test/isolation/specs/ivm-refresh-insert.spec new file mode 100644 index 00000000000..d7181251962 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert2.spec b/src/test/isolation/specs/ivm-refresh-insert2.spec new file mode 100644 index 00000000000..f2d1d5013f2 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert2.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in REPEATABLE READ isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert3.spec b/src/test/isolation/specs/ivm-refresh-insert3.spec new file mode 100644 index 00000000000..0ec2b1d1de0 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert3.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in SERIALIZABLE isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/regress/expected/incremental_matview.out b/src/test/regress/expected/incremental_matview.out new file mode 100644 index 00000000000..f215aa88e48 --- /dev/null +++ b/src/test/regress/expected/incremental_matview.out @@ -0,0 +1,1100 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ERROR: materialized view "mv_ivm_1" has not been populated +HINT: Use the REFRESH MATERIALIZED VIEW command. +REFRESH MATERIALIZED VIEW mv_ivm_1; +NOTICE: could not create an index on materialized view "mv_ivm_1" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 17 +(1 row) + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 1 +(1 row) + +ROLLBACK; +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_rename_index" on materialized view "mv_ivm_rename" +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +ERROR: IVM column can not be renamed +DROP MATERIALIZED VIEW mv_ivm_rename; +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_unique_index" on materialized view "mv_ivm_unique" +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +ERROR: unique index creation on IVM columns is not supported +DROP MATERIALIZED VIEW mv_ivm_unique; +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +NOTICE: could not create an index on materialized view "mv_ivm_func" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +NOTICE: could not create an index on materialized view "mv_ivm_no_tbl" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_duplicate" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +NOTICE: created index "mv_ivm_distinct_index" on materialized view "mv_ivm_distinct" +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 20 + 30 + 40 + 50 +(6 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +ROLLBACK; +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 120 | 2 | 60.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+---------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 220 | 2 | 110.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 20 | 1 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 120 | 2 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; + sum | count +-----+------- +(0 rows) + +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; + i | sum | count +---+-----+------- +(0 rows) + +ROLLBACK; +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 150 | 5 | 30.0000000000000000 +(1 row) + +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 210 | 6 | 35.0000000000000000 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +NOTICE: created index "mv_ivm_avg_bug_index" on materialized view "mv_ivm_avg_bug" +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 3 | 3.3333333333333333 + 2 | 80 | 3 | 26.6666666666666667 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_min_max_index" on materialized view "mv_ivm_min_max" +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 10 + 2 | 20 | 20 + 3 | 30 | 30 + 4 | 40 | 40 + 5 | 50 | 50 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 12 + 2 | 20 | 22 + 3 | 30 | 32 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 11 | 12 + 2 | 20 | 22 + 3 | 30 | 31 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min_max" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 50 +(1 row) + +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 0 | 70 +(1 row) + +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 60 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + | +(1 row) + +ROLLBACK; +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min; + min +----- + 10 +(1 row) + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + min +----- + 20 +(1 row) + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; + min +----- + 30 +(1 row) + +ROLLBACK; +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | sum +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | b +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ERROR: too many column names were specified +ROLLBACK; +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +NOTICE: could not create an index on materialized view "mv_self" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +----+---- + 10 | 10 + 20 | 20 + 30 | 30 +(3 rows) + +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 30 | 30 + 40 | 40 + 200 | 200 +(3 rows) + +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 130 | 130 + 300 | 300 +(4 rows) + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 70 | 70 + 70 | 77 + 77 | 70 + 77 | 77 + 130 | 130 + 300 | 300 +(8 rows) + +ROLLBACK; +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY v1; + v1 | v2 +----+----- + 10 | 100 + 20 | 200 + 30 | 300 +(3 rows) + +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv ORDER BY v1; + v1 | v2 +------+----- + 10 | 100 + 11 | 100 + 1020 | 200 + 1020 | 222 +(4 rows) + +ROLLBACK; +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +NOTICE: created index "mv_ri_index" on materialized view "mv_ri" +SELECT * FROM mv_ri ORDER BY i1; + i1 | i2 +----+---- + 1 | 1 + 2 | 2 + 3 | 3 +(3 rows) + +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; + i1 | i2 +----+---- + 3 | 3 + 10 | 10 +(2 rows) + +ROLLBACK; +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | +(2 rows) + +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | 20 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i +--- +(0 rows) + +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; + i +--- + 1 + +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 30 + | 3 +(2 rows) + +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 300 + | 30 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 1 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 4 +(1 row) + +ROLLBACK; +-- IMMV containing user defined type +BEGIN; +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: return type mytype is only a shell +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: argument type mytype is only a shell +LINE 1: CREATE FUNCTION mytype_out(mytype) + ^ +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +NOTICE: could not create an index on materialized view "mv_mytype" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + x +--- + 1 +(1 row) + +ROLLBACK; +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +ERROR: OUTER JOIN is not supported on incrementally maintainable materialized view +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +ERROR: CTE is not supported on incrementally maintainable materialized view +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +ERROR: ORDER BY clause is not supported on incrementally maintainable materialized view +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; +ERROR: HAVING clause is not supported on incrementally maintainable materialized view +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; +ERROR: mutable function is not supported on incrementally maintainable materialized view +HINT: functions must be marked IMMUTABLE +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; +ERROR: LIMIT/OFFSET clause is not supported on incrementally maintainable materialized view +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; +ERROR: DISTINCT ON is not supported on incrementally maintainable materialized view +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); +ERROR: TABLESAMPLE clause is not supported on incrementally maintainable materialized view +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; +ERROR: window functions are not supported on incrementally maintainable materialized view +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +ERROR: aggregate function with FILTER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +ERROR: aggregate function with DISTINCT arguments is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +ERROR: aggregate function with ORDER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); +ERROR: GROUPING SETS, ROLLUP, or CUBE clauses is not supported on incrementally maintainable materialized view +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ERROR: inheritance parent is not supported on incrementally maintainable materialized view +ROLLBACK; +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; +ERROR: UNION/INTERSECT/EXCEPT statements are not supported on incrementally maintainable materialized view +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; +ERROR: empty target list is not supported on incrementally maintainable materialized view +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; +ERROR: FOR UPDATE/SHARE clause is not supported on incrementally maintainable materialized view +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; +ERROR: column name __ivm_count__ is not supported on incrementally maintainable materialized view +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; +ERROR: GROUP BY expression not appearing in select list is not supported on incrementally maintainable materialized view +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); +ERROR: VALUES is not supported on incrementally maintainable materialized view +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +NOTICE: role "regress_ivm_admin" does not exist, skipping +DROP USER IF EXISTS regress_ivm_user; +NOTICE: role "regress_ivm_user" does not exist, skipping +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +NOTICE: could not create an index on materialized view "ivm_rls" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user +(1 row) + +RESET SESSION AUTHORIZATION; +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user + 3 | baz | regress_ivm_user +(2 rows) + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +-- +(1 row) + +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+-------+------------------ + 2 | bar | regress_ivm_user + 3 | baz | regress_ivm_user + 6 | corge | regress_ivm_user +(3 rows) + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +NOTICE: could not create an index on materialized view "ivm_rls2" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +RESET SESSION AUTHORIZATION; +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +-- +(1 row) + +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + id | data | owner | num +----+-------+------------------+--------- + 2 | bar | regress_ivm_user | two + 3 | baz_2 | regress_ivm_user | three_2 + 6 | corge | regress_ivm_user | six +(3 rows) + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +NOTICE: could not create an index on materialized view "mv_update_same" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + i +--- + 2 +(1 row) + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +NOTICE: created index "mv_self_ref_index" on materialized view "mv_self_ref" +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; + a | b +----+---- + 11 | + 12 | 11 + 13 | 12 +(3 rows) + +ROLLBACK; +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; +NOTICE: created index "mv_idx1_index" on materialized view "mv_idx1" +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; +NOTICE: created index "mv_idx2_index" on materialized view "mv_idx2" +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; +NOTICE: created index "mv_idx3_index" on materialized view "mv_idx3" +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +NOTICE: could not create an index on materialized view "mv_idx4" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; +NOTICE: could not create an index on materialized view "mv_idx5" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); +NOTICE: could not create an index on materialized view "mv_idx6" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ERROR: data type json has no default operator class for access method "btree" +ROLLBACK; +-- cleanup +DROP TABLE rls_tbl CASCADE; +NOTICE: drop cascades to 2 other objects +DETAIL: drop cascades to materialized view ivm_rls +drop cascades to materialized view ivm_rls2 +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; +DROP TABLE mv_base_b CASCADE; +NOTICE: drop cascades to 3 other objects +DETAIL: drop cascades to materialized view mv_ivm_1 +drop cascades to view b_view +drop cascades to materialized view b_mview +DROP TABLE mv_base_a CASCADE; diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index 8fa0a6c47fb..7caca5f64fd 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -77,6 +77,7 @@ test: brin_bloom brin_multi # Another group of parallel tests # ---------- test: create_table_like alter_generic alter_operator misc async dbsize merge misc_functions nls sysviews tsrf tid tidscan tidrangescan collate.utf8 collate.icu.utf8 incremental_sort create_role without_overlaps generated_virtual +test: incremental_matview # collate.linux.utf8 and collate.icu.utf8 tests cannot be run in parallel with each other # psql depends on create_am diff --git a/src/test/regress/sql/incremental_matview.sql b/src/test/regress/sql/incremental_matview.sql new file mode 100644 index 00000000000..2d55c393d6f --- /dev/null +++ b/src/test/regress/sql/incremental_matview.sql @@ -0,0 +1,580 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); + +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +REFRESH MATERIALIZED VIEW mv_ivm_1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; + +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; +ROLLBACK; + +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +DROP MATERIALIZED VIEW mv_ivm_rename; + +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +DROP MATERIALIZED VIEW mv_ivm_unique; + +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; + + +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +ROLLBACK; + +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +ROLLBACK; + +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +ROLLBACK; + +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +ROLLBACK; + +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +ROLLBACK; + +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min; + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); + +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; +ROLLBACK; + +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +SELECT * FROM mv_self ORDER BY v1; +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; +SELECT * FROM mv_self ORDER BY v1; + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + +ROLLBACK; + +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +SELECT * FROM mv ORDER BY v1; +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; +SELECT * FROM mv ORDER BY v1; +ROLLBACK; + +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +SELECT * FROM mv_ri ORDER BY i1; +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; +ROLLBACK; + +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +-- IMMV containing user defined type +BEGIN; + +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); + +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; + +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); + +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); + +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + +ROLLBACK; + +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; + +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; + +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; + +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; + +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; + +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); + +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; + +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); + +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ROLLBACK; + +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; + +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; + +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; + +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; + +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; + +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; + +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); + +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +DROP USER IF EXISTS regress_ivm_user; +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; + +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); + +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; + +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; + +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; +RESET SESSION AUTHORIZATION; + +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +RESET SESSION AUTHORIZATION; + +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; +ROLLBACK; + +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); + +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; + +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; + +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; + +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; + +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); + +ROLLBACK; + +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ROLLBACK; + +-- cleanup + +DROP TABLE rls_tbl CASCADE; +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; + +DROP TABLE mv_base_b CASCADE; +DROP TABLE mv_base_a CASCADE; -- 2.43.0 --Multipart=_Wed__1_Jul_2026_00_04_01_+0900_OVSy2WWK_9aByzDJ Content-Type: text/x-diff; name="v38-0009-Add-support-for-min-max-aggregates-for-IVM.patch" Content-Disposition: attachment; filename="v38-0009-Add-support-for-min-max-aggregates-for-IVM.patch" Content-Transfer-Encoding: 7bit ^ permalink raw reply [nested|flat] 78+ messages in thread
* [PATCH v37 10/11] Add regression tests for Incremental View Maintenance @ 2026-05-29 09:31 Yugo Nagata <[email protected]> 0 siblings, 0 replies; 78+ messages in thread From: Yugo Nagata @ 2026-05-29 09:31 UTC (permalink / raw) --- src/test/isolation/isolation_schedule | 9 + .../regress/expected/incremental_matview.out | 1100 +++++++++++++++++ src/test/regress/parallel_schedule | 1 + src/test/regress/sql/incremental_matview.sql | 580 +++++++++ 4 files changed, 1690 insertions(+) create mode 100644 src/test/regress/expected/incremental_matview.out create mode 100644 src/test/regress/sql/incremental_matview.sql diff --git a/src/test/isolation/isolation_schedule b/src/test/isolation/isolation_schedule index 15c33fad4c5..111fd465207 100644 --- a/src/test/isolation/isolation_schedule +++ b/src/test/isolation/isolation_schedule @@ -127,3 +127,12 @@ test: matview-write-skew test: lock-nowait test: for-portion-of test: ddl-dependency-locking +test: ivm-create-insert +test: ivm-create-insert2 +test: ivm-create-insert3 +test: ivm-insert-insert +test: ivm-insert-insert2 +test: ivm-insert-insert3 +test: ivm-refresh-insert +test: ivm-refresh-insert2 +test: ivm-refresh-insert3 diff --git a/src/test/regress/expected/incremental_matview.out b/src/test/regress/expected/incremental_matview.out new file mode 100644 index 00000000000..f215aa88e48 --- /dev/null +++ b/src/test/regress/expected/incremental_matview.out @@ -0,0 +1,1100 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ERROR: materialized view "mv_ivm_1" has not been populated +HINT: Use the REFRESH MATERIALIZED VIEW command. +REFRESH MATERIALIZED VIEW mv_ivm_1; +NOTICE: could not create an index on materialized view "mv_ivm_1" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 17 +(1 row) + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 1 +(1 row) + +ROLLBACK; +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_rename_index" on materialized view "mv_ivm_rename" +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +ERROR: IVM column can not be renamed +DROP MATERIALIZED VIEW mv_ivm_rename; +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_unique_index" on materialized view "mv_ivm_unique" +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +ERROR: unique index creation on IVM columns is not supported +DROP MATERIALIZED VIEW mv_ivm_unique; +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +NOTICE: could not create an index on materialized view "mv_ivm_func" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +NOTICE: could not create an index on materialized view "mv_ivm_no_tbl" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_duplicate" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +NOTICE: created index "mv_ivm_distinct_index" on materialized view "mv_ivm_distinct" +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 20 + 30 + 40 + 50 +(6 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +ROLLBACK; +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 120 | 2 | 60.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+---------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 220 | 2 | 110.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 20 | 1 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 120 | 2 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; + sum | count +-----+------- +(0 rows) + +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; + i | sum | count +---+-----+------- +(0 rows) + +ROLLBACK; +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 150 | 5 | 30.0000000000000000 +(1 row) + +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 210 | 6 | 35.0000000000000000 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +NOTICE: created index "mv_ivm_avg_bug_index" on materialized view "mv_ivm_avg_bug" +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 3 | 3.3333333333333333 + 2 | 80 | 3 | 26.6666666666666667 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_min_max_index" on materialized view "mv_ivm_min_max" +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 10 + 2 | 20 | 20 + 3 | 30 | 30 + 4 | 40 | 40 + 5 | 50 | 50 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 12 + 2 | 20 | 22 + 3 | 30 | 32 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 11 | 12 + 2 | 20 | 22 + 3 | 30 | 31 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min_max" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 50 +(1 row) + +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 0 | 70 +(1 row) + +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 60 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + | +(1 row) + +ROLLBACK; +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min; + min +----- + 10 +(1 row) + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + min +----- + 20 +(1 row) + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; + min +----- + 30 +(1 row) + +ROLLBACK; +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | sum +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | b +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ERROR: too many column names were specified +ROLLBACK; +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +NOTICE: could not create an index on materialized view "mv_self" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +----+---- + 10 | 10 + 20 | 20 + 30 | 30 +(3 rows) + +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 30 | 30 + 40 | 40 + 200 | 200 +(3 rows) + +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 130 | 130 + 300 | 300 +(4 rows) + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 70 | 70 + 70 | 77 + 77 | 70 + 77 | 77 + 130 | 130 + 300 | 300 +(8 rows) + +ROLLBACK; +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY v1; + v1 | v2 +----+----- + 10 | 100 + 20 | 200 + 30 | 300 +(3 rows) + +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv ORDER BY v1; + v1 | v2 +------+----- + 10 | 100 + 11 | 100 + 1020 | 200 + 1020 | 222 +(4 rows) + +ROLLBACK; +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +NOTICE: created index "mv_ri_index" on materialized view "mv_ri" +SELECT * FROM mv_ri ORDER BY i1; + i1 | i2 +----+---- + 1 | 1 + 2 | 2 + 3 | 3 +(3 rows) + +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; + i1 | i2 +----+---- + 3 | 3 + 10 | 10 +(2 rows) + +ROLLBACK; +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | +(2 rows) + +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | 20 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i +--- +(0 rows) + +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; + i +--- + 1 + +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 30 + | 3 +(2 rows) + +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 300 + | 30 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 1 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 4 +(1 row) + +ROLLBACK; +-- IMMV containing user defined type +BEGIN; +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: return type mytype is only a shell +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: argument type mytype is only a shell +LINE 1: CREATE FUNCTION mytype_out(mytype) + ^ +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +NOTICE: could not create an index on materialized view "mv_mytype" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + x +--- + 1 +(1 row) + +ROLLBACK; +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +ERROR: OUTER JOIN is not supported on incrementally maintainable materialized view +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +ERROR: CTE is not supported on incrementally maintainable materialized view +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +ERROR: ORDER BY clause is not supported on incrementally maintainable materialized view +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; +ERROR: HAVING clause is not supported on incrementally maintainable materialized view +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; +ERROR: mutable function is not supported on incrementally maintainable materialized view +HINT: functions must be marked IMMUTABLE +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; +ERROR: LIMIT/OFFSET clause is not supported on incrementally maintainable materialized view +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; +ERROR: DISTINCT ON is not supported on incrementally maintainable materialized view +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); +ERROR: TABLESAMPLE clause is not supported on incrementally maintainable materialized view +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; +ERROR: window functions are not supported on incrementally maintainable materialized view +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +ERROR: aggregate function with FILTER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +ERROR: aggregate function with DISTINCT arguments is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +ERROR: aggregate function with ORDER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); +ERROR: GROUPING SETS, ROLLUP, or CUBE clauses is not supported on incrementally maintainable materialized view +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ERROR: inheritance parent is not supported on incrementally maintainable materialized view +ROLLBACK; +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; +ERROR: UNION/INTERSECT/EXCEPT statements are not supported on incrementally maintainable materialized view +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; +ERROR: empty target list is not supported on incrementally maintainable materialized view +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; +ERROR: FOR UPDATE/SHARE clause is not supported on incrementally maintainable materialized view +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; +ERROR: column name __ivm_count__ is not supported on incrementally maintainable materialized view +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; +ERROR: GROUP BY expression not appearing in select list is not supported on incrementally maintainable materialized view +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); +ERROR: VALUES is not supported on incrementally maintainable materialized view +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +NOTICE: role "regress_ivm_admin" does not exist, skipping +DROP USER IF EXISTS regress_ivm_user; +NOTICE: role "regress_ivm_user" does not exist, skipping +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +NOTICE: could not create an index on materialized view "ivm_rls" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user +(1 row) + +RESET SESSION AUTHORIZATION; +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user + 3 | baz | regress_ivm_user +(2 rows) + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +-- +(1 row) + +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+-------+------------------ + 2 | bar | regress_ivm_user + 3 | baz | regress_ivm_user + 6 | corge | regress_ivm_user +(3 rows) + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +NOTICE: could not create an index on materialized view "ivm_rls2" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +RESET SESSION AUTHORIZATION; +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +-- +(1 row) + +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + id | data | owner | num +----+-------+------------------+--------- + 2 | bar | regress_ivm_user | two + 3 | baz_2 | regress_ivm_user | three_2 + 6 | corge | regress_ivm_user | six +(3 rows) + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +NOTICE: could not create an index on materialized view "mv_update_same" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + i +--- + 2 +(1 row) + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +NOTICE: created index "mv_self_ref_index" on materialized view "mv_self_ref" +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; + a | b +----+---- + 11 | + 12 | 11 + 13 | 12 +(3 rows) + +ROLLBACK; +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; +NOTICE: created index "mv_idx1_index" on materialized view "mv_idx1" +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; +NOTICE: created index "mv_idx2_index" on materialized view "mv_idx2" +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; +NOTICE: created index "mv_idx3_index" on materialized view "mv_idx3" +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +NOTICE: could not create an index on materialized view "mv_idx4" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; +NOTICE: could not create an index on materialized view "mv_idx5" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); +NOTICE: could not create an index on materialized view "mv_idx6" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ERROR: data type json has no default operator class for access method "btree" +ROLLBACK; +-- cleanup +DROP TABLE rls_tbl CASCADE; +NOTICE: drop cascades to 2 other objects +DETAIL: drop cascades to materialized view ivm_rls +drop cascades to materialized view ivm_rls2 +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; +DROP TABLE mv_base_b CASCADE; +NOTICE: drop cascades to 3 other objects +DETAIL: drop cascades to materialized view mv_ivm_1 +drop cascades to view b_view +drop cascades to materialized view b_mview +DROP TABLE mv_base_a CASCADE; diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index 8fa0a6c47fb..7caca5f64fd 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -77,6 +77,7 @@ test: brin_bloom brin_multi # Another group of parallel tests # ---------- test: create_table_like alter_generic alter_operator misc async dbsize merge misc_functions nls sysviews tsrf tid tidscan tidrangescan collate.utf8 collate.icu.utf8 incremental_sort create_role without_overlaps generated_virtual +test: incremental_matview # collate.linux.utf8 and collate.icu.utf8 tests cannot be run in parallel with each other # psql depends on create_am diff --git a/src/test/regress/sql/incremental_matview.sql b/src/test/regress/sql/incremental_matview.sql new file mode 100644 index 00000000000..2d55c393d6f --- /dev/null +++ b/src/test/regress/sql/incremental_matview.sql @@ -0,0 +1,580 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); + +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +REFRESH MATERIALIZED VIEW mv_ivm_1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; + +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; +ROLLBACK; + +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +DROP MATERIALIZED VIEW mv_ivm_rename; + +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +DROP MATERIALIZED VIEW mv_ivm_unique; + +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; + + +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +ROLLBACK; + +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +ROLLBACK; + +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +ROLLBACK; + +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +ROLLBACK; + +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +ROLLBACK; + +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min; + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); + +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; +ROLLBACK; + +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +SELECT * FROM mv_self ORDER BY v1; +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; +SELECT * FROM mv_self ORDER BY v1; + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + +ROLLBACK; + +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +SELECT * FROM mv ORDER BY v1; +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; +SELECT * FROM mv ORDER BY v1; +ROLLBACK; + +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +SELECT * FROM mv_ri ORDER BY i1; +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; +ROLLBACK; + +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +-- IMMV containing user defined type +BEGIN; + +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); + +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; + +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); + +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); + +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + +ROLLBACK; + +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; + +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; + +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; + +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; + +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; + +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); + +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; + +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); + +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ROLLBACK; + +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; + +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; + +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; + +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; + +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; + +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; + +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); + +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +DROP USER IF EXISTS regress_ivm_user; +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; + +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); + +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; + +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; + +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; +RESET SESSION AUTHORIZATION; + +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +RESET SESSION AUTHORIZATION; + +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; +ROLLBACK; + +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); + +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; + +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; + +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; + +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; + +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); + +ROLLBACK; + +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ROLLBACK; + +-- cleanup + +DROP TABLE rls_tbl CASCADE; +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; + +DROP TABLE mv_base_b CASCADE; +DROP TABLE mv_base_a CASCADE; -- 2.43.0 --Multipart=_Fri__29_May_2026_23_14_17_+0900_Te0o73X2VqYK57Gd Content-Type: text/x-diff; name="v37-0009-Add-support-for-min-max-aggregates-for-IVM.patch" Content-Disposition: attachment; filename="v37-0009-Add-support-for-min-max-aggregates-for-IVM.patch" Content-Transfer-Encoding: 7bit ^ permalink raw reply [nested|flat] 78+ messages in thread
* [PATCH v37 10/11] Add regression tests for Incremental View Maintenance @ 2026-05-29 09:31 Yugo Nagata <[email protected]> 0 siblings, 0 replies; 78+ messages in thread From: Yugo Nagata @ 2026-05-29 09:31 UTC (permalink / raw) --- src/test/isolation/isolation_schedule | 9 + .../regress/expected/incremental_matview.out | 1100 +++++++++++++++++ src/test/regress/parallel_schedule | 1 + src/test/regress/sql/incremental_matview.sql | 580 +++++++++ 4 files changed, 1690 insertions(+) create mode 100644 src/test/regress/expected/incremental_matview.out create mode 100644 src/test/regress/sql/incremental_matview.sql diff --git a/src/test/isolation/isolation_schedule b/src/test/isolation/isolation_schedule index 15c33fad4c5..111fd465207 100644 --- a/src/test/isolation/isolation_schedule +++ b/src/test/isolation/isolation_schedule @@ -127,3 +127,12 @@ test: matview-write-skew test: lock-nowait test: for-portion-of test: ddl-dependency-locking +test: ivm-create-insert +test: ivm-create-insert2 +test: ivm-create-insert3 +test: ivm-insert-insert +test: ivm-insert-insert2 +test: ivm-insert-insert3 +test: ivm-refresh-insert +test: ivm-refresh-insert2 +test: ivm-refresh-insert3 diff --git a/src/test/regress/expected/incremental_matview.out b/src/test/regress/expected/incremental_matview.out new file mode 100644 index 00000000000..f215aa88e48 --- /dev/null +++ b/src/test/regress/expected/incremental_matview.out @@ -0,0 +1,1100 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ERROR: materialized view "mv_ivm_1" has not been populated +HINT: Use the REFRESH MATERIALIZED VIEW command. +REFRESH MATERIALIZED VIEW mv_ivm_1; +NOTICE: could not create an index on materialized view "mv_ivm_1" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 17 +(1 row) + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 1 +(1 row) + +ROLLBACK; +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_rename_index" on materialized view "mv_ivm_rename" +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +ERROR: IVM column can not be renamed +DROP MATERIALIZED VIEW mv_ivm_rename; +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_unique_index" on materialized view "mv_ivm_unique" +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +ERROR: unique index creation on IVM columns is not supported +DROP MATERIALIZED VIEW mv_ivm_unique; +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +NOTICE: could not create an index on materialized view "mv_ivm_func" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +NOTICE: could not create an index on materialized view "mv_ivm_no_tbl" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_duplicate" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +NOTICE: created index "mv_ivm_distinct_index" on materialized view "mv_ivm_distinct" +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 20 + 30 + 40 + 50 +(6 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +ROLLBACK; +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 120 | 2 | 60.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+---------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 220 | 2 | 110.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 20 | 1 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 120 | 2 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; + sum | count +-----+------- +(0 rows) + +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; + i | sum | count +---+-----+------- +(0 rows) + +ROLLBACK; +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 150 | 5 | 30.0000000000000000 +(1 row) + +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 210 | 6 | 35.0000000000000000 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +NOTICE: created index "mv_ivm_avg_bug_index" on materialized view "mv_ivm_avg_bug" +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 3 | 3.3333333333333333 + 2 | 80 | 3 | 26.6666666666666667 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_min_max_index" on materialized view "mv_ivm_min_max" +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 10 + 2 | 20 | 20 + 3 | 30 | 30 + 4 | 40 | 40 + 5 | 50 | 50 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 12 + 2 | 20 | 22 + 3 | 30 | 32 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 11 | 12 + 2 | 20 | 22 + 3 | 30 | 31 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min_max" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 50 +(1 row) + +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 0 | 70 +(1 row) + +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 60 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + | +(1 row) + +ROLLBACK; +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min; + min +----- + 10 +(1 row) + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + min +----- + 20 +(1 row) + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; + min +----- + 30 +(1 row) + +ROLLBACK; +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | sum +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | b +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ERROR: too many column names were specified +ROLLBACK; +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +NOTICE: could not create an index on materialized view "mv_self" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +----+---- + 10 | 10 + 20 | 20 + 30 | 30 +(3 rows) + +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 30 | 30 + 40 | 40 + 200 | 200 +(3 rows) + +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 130 | 130 + 300 | 300 +(4 rows) + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 70 | 70 + 70 | 77 + 77 | 70 + 77 | 77 + 130 | 130 + 300 | 300 +(8 rows) + +ROLLBACK; +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY v1; + v1 | v2 +----+----- + 10 | 100 + 20 | 200 + 30 | 300 +(3 rows) + +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv ORDER BY v1; + v1 | v2 +------+----- + 10 | 100 + 11 | 100 + 1020 | 200 + 1020 | 222 +(4 rows) + +ROLLBACK; +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +NOTICE: created index "mv_ri_index" on materialized view "mv_ri" +SELECT * FROM mv_ri ORDER BY i1; + i1 | i2 +----+---- + 1 | 1 + 2 | 2 + 3 | 3 +(3 rows) + +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; + i1 | i2 +----+---- + 3 | 3 + 10 | 10 +(2 rows) + +ROLLBACK; +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | +(2 rows) + +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | 20 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i +--- +(0 rows) + +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; + i +--- + 1 + +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 30 + | 3 +(2 rows) + +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 300 + | 30 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 1 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 4 +(1 row) + +ROLLBACK; +-- IMMV containing user defined type +BEGIN; +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: return type mytype is only a shell +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: argument type mytype is only a shell +LINE 1: CREATE FUNCTION mytype_out(mytype) + ^ +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +NOTICE: could not create an index on materialized view "mv_mytype" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + x +--- + 1 +(1 row) + +ROLLBACK; +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +ERROR: OUTER JOIN is not supported on incrementally maintainable materialized view +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +ERROR: CTE is not supported on incrementally maintainable materialized view +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +ERROR: ORDER BY clause is not supported on incrementally maintainable materialized view +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; +ERROR: HAVING clause is not supported on incrementally maintainable materialized view +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; +ERROR: mutable function is not supported on incrementally maintainable materialized view +HINT: functions must be marked IMMUTABLE +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; +ERROR: LIMIT/OFFSET clause is not supported on incrementally maintainable materialized view +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; +ERROR: DISTINCT ON is not supported on incrementally maintainable materialized view +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); +ERROR: TABLESAMPLE clause is not supported on incrementally maintainable materialized view +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; +ERROR: window functions are not supported on incrementally maintainable materialized view +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +ERROR: aggregate function with FILTER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +ERROR: aggregate function with DISTINCT arguments is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +ERROR: aggregate function with ORDER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); +ERROR: GROUPING SETS, ROLLUP, or CUBE clauses is not supported on incrementally maintainable materialized view +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ERROR: inheritance parent is not supported on incrementally maintainable materialized view +ROLLBACK; +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; +ERROR: UNION/INTERSECT/EXCEPT statements are not supported on incrementally maintainable materialized view +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; +ERROR: empty target list is not supported on incrementally maintainable materialized view +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; +ERROR: FOR UPDATE/SHARE clause is not supported on incrementally maintainable materialized view +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; +ERROR: column name __ivm_count__ is not supported on incrementally maintainable materialized view +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; +ERROR: GROUP BY expression not appearing in select list is not supported on incrementally maintainable materialized view +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); +ERROR: VALUES is not supported on incrementally maintainable materialized view +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +NOTICE: role "regress_ivm_admin" does not exist, skipping +DROP USER IF EXISTS regress_ivm_user; +NOTICE: role "regress_ivm_user" does not exist, skipping +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +NOTICE: could not create an index on materialized view "ivm_rls" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user +(1 row) + +RESET SESSION AUTHORIZATION; +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user + 3 | baz | regress_ivm_user +(2 rows) + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +-- +(1 row) + +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+-------+------------------ + 2 | bar | regress_ivm_user + 3 | baz | regress_ivm_user + 6 | corge | regress_ivm_user +(3 rows) + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +NOTICE: could not create an index on materialized view "ivm_rls2" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +RESET SESSION AUTHORIZATION; +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +-- +(1 row) + +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + id | data | owner | num +----+-------+------------------+--------- + 2 | bar | regress_ivm_user | two + 3 | baz_2 | regress_ivm_user | three_2 + 6 | corge | regress_ivm_user | six +(3 rows) + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +NOTICE: could not create an index on materialized view "mv_update_same" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + i +--- + 2 +(1 row) + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +NOTICE: created index "mv_self_ref_index" on materialized view "mv_self_ref" +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; + a | b +----+---- + 11 | + 12 | 11 + 13 | 12 +(3 rows) + +ROLLBACK; +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; +NOTICE: created index "mv_idx1_index" on materialized view "mv_idx1" +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; +NOTICE: created index "mv_idx2_index" on materialized view "mv_idx2" +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; +NOTICE: created index "mv_idx3_index" on materialized view "mv_idx3" +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +NOTICE: could not create an index on materialized view "mv_idx4" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; +NOTICE: could not create an index on materialized view "mv_idx5" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); +NOTICE: could not create an index on materialized view "mv_idx6" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ERROR: data type json has no default operator class for access method "btree" +ROLLBACK; +-- cleanup +DROP TABLE rls_tbl CASCADE; +NOTICE: drop cascades to 2 other objects +DETAIL: drop cascades to materialized view ivm_rls +drop cascades to materialized view ivm_rls2 +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; +DROP TABLE mv_base_b CASCADE; +NOTICE: drop cascades to 3 other objects +DETAIL: drop cascades to materialized view mv_ivm_1 +drop cascades to view b_view +drop cascades to materialized view b_mview +DROP TABLE mv_base_a CASCADE; diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index 8fa0a6c47fb..7caca5f64fd 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -77,6 +77,7 @@ test: brin_bloom brin_multi # Another group of parallel tests # ---------- test: create_table_like alter_generic alter_operator misc async dbsize merge misc_functions nls sysviews tsrf tid tidscan tidrangescan collate.utf8 collate.icu.utf8 incremental_sort create_role without_overlaps generated_virtual +test: incremental_matview # collate.linux.utf8 and collate.icu.utf8 tests cannot be run in parallel with each other # psql depends on create_am diff --git a/src/test/regress/sql/incremental_matview.sql b/src/test/regress/sql/incremental_matview.sql new file mode 100644 index 00000000000..2d55c393d6f --- /dev/null +++ b/src/test/regress/sql/incremental_matview.sql @@ -0,0 +1,580 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); + +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +REFRESH MATERIALIZED VIEW mv_ivm_1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; + +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; +ROLLBACK; + +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +DROP MATERIALIZED VIEW mv_ivm_rename; + +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +DROP MATERIALIZED VIEW mv_ivm_unique; + +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; + + +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +ROLLBACK; + +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +ROLLBACK; + +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +ROLLBACK; + +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +ROLLBACK; + +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +ROLLBACK; + +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min; + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); + +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; +ROLLBACK; + +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +SELECT * FROM mv_self ORDER BY v1; +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; +SELECT * FROM mv_self ORDER BY v1; + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + +ROLLBACK; + +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +SELECT * FROM mv ORDER BY v1; +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; +SELECT * FROM mv ORDER BY v1; +ROLLBACK; + +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +SELECT * FROM mv_ri ORDER BY i1; +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; +ROLLBACK; + +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +-- IMMV containing user defined type +BEGIN; + +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); + +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; + +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); + +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); + +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + +ROLLBACK; + +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; + +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; + +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; + +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; + +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; + +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); + +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; + +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); + +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ROLLBACK; + +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; + +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; + +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; + +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; + +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; + +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; + +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); + +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +DROP USER IF EXISTS regress_ivm_user; +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; + +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); + +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; + +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; + +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; +RESET SESSION AUTHORIZATION; + +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +RESET SESSION AUTHORIZATION; + +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; +ROLLBACK; + +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); + +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; + +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; + +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; + +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; + +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); + +ROLLBACK; + +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ROLLBACK; + +-- cleanup + +DROP TABLE rls_tbl CASCADE; +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; + +DROP TABLE mv_base_b CASCADE; +DROP TABLE mv_base_a CASCADE; -- 2.43.0 --Multipart=_Fri__29_May_2026_23_14_17_+0900_Te0o73X2VqYK57Gd Content-Type: text/x-diff; name="v37-0009-Add-support-for-min-max-aggregates-for-IVM.patch" Content-Disposition: attachment; filename="v37-0009-Add-support-for-min-max-aggregates-for-IVM.patch" Content-Transfer-Encoding: 7bit ^ permalink raw reply [nested|flat] 78+ messages in thread
* [PATCH v38 10/11] Add regression tests for Incremental View Maintenance @ 2026-05-29 09:31 Yugo Nagata <[email protected]> 0 siblings, 0 replies; 78+ messages in thread From: Yugo Nagata @ 2026-05-29 09:31 UTC (permalink / raw) --- .../isolation/expected/ivm-create-insert.out | 285 +++++ .../isolation/expected/ivm-create-insert2.out | 305 +++++ .../isolation/expected/ivm-create-insert3.out | 305 +++++ .../isolation/expected/ivm-insert-insert.out | 497 ++++++++ .../isolation/expected/ivm-insert-insert2.out | 373 ++++++ .../isolation/expected/ivm-insert-insert3.out | 373 ++++++ .../isolation/expected/ivm-refresh-insert.out | 213 ++++ .../expected/ivm-refresh-insert2.out | 191 +++ .../expected/ivm-refresh-insert3.out | 191 +++ src/test/isolation/isolation_schedule | 9 + .../isolation/specs/ivm-create-insert.spec | 47 + .../isolation/specs/ivm-create-insert2.spec | 54 + .../isolation/specs/ivm-create-insert3.spec | 54 + .../isolation/specs/ivm-insert-insert.spec | 62 + .../isolation/specs/ivm-insert-insert2.spec | 62 + .../isolation/specs/ivm-insert-insert3.spec | 62 + .../isolation/specs/ivm-refresh-insert.spec | 46 + .../isolation/specs/ivm-refresh-insert2.spec | 46 + .../isolation/specs/ivm-refresh-insert3.spec | 46 + .../regress/expected/incremental_matview.out | 1100 +++++++++++++++++ src/test/regress/parallel_schedule | 1 + src/test/regress/sql/incremental_matview.sql | 580 +++++++++ 22 files changed, 4902 insertions(+) create mode 100644 src/test/isolation/expected/ivm-create-insert.out create mode 100644 src/test/isolation/expected/ivm-create-insert2.out create mode 100644 src/test/isolation/expected/ivm-create-insert3.out create mode 100644 src/test/isolation/expected/ivm-insert-insert.out create mode 100644 src/test/isolation/expected/ivm-insert-insert2.out create mode 100644 src/test/isolation/expected/ivm-insert-insert3.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert2.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert3.out create mode 100644 src/test/isolation/specs/ivm-create-insert.spec create mode 100644 src/test/isolation/specs/ivm-create-insert2.spec create mode 100644 src/test/isolation/specs/ivm-create-insert3.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert2.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert3.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert2.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert3.spec create mode 100644 src/test/regress/expected/incremental_matview.out create mode 100644 src/test/regress/sql/incremental_matview.sql diff --git a/src/test/isolation/expected/ivm-create-insert.out b/src/test/isolation/expected/ivm-create-insert.out new file mode 100644 index 00000000000..5da00043aba --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert.out @@ -0,0 +1,285 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-create-insert2.out b/src/test/isolation/expected/ivm-create-insert2.out new file mode 100644 index 00000000000..907d892c6d4 --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert2.out @@ -0,0 +1,305 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + diff --git a/src/test/isolation/expected/ivm-create-insert3.out b/src/test/isolation/expected/ivm-create-insert3.out new file mode 100644 index 00000000000..907d892c6d4 --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert3.out @@ -0,0 +1,305 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert.out b/src/test/isolation/expected/ivm-insert-insert.out new file mode 100644 index 00000000000..5ca4cfea677 --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert.out @@ -0,0 +1,497 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; <waiting ...> +step c1: COMMIT; +step update2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; <waiting ...> +step c1: COMMIT; +step update2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; <waiting ...> +step c2: COMMIT; +step update1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; <waiting ...> +step c2: COMMIT; +step update1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); <waiting ...> +step c1: COMMIT; +step insert2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); <waiting ...> +step c1: COMMIT; +step insert2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); <waiting ...> +step c2: COMMIT; +step insert1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); <waiting ...> +step c2: COMMIT; +step insert1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert2.out b/src/test/isolation/expected/ivm-insert-insert2.out new file mode 100644 index 00000000000..e1c66d4de5e --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert2.out @@ -0,0 +1,373 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert3.out b/src/test/isolation/expected/ivm-insert-insert3.out new file mode 100644 index 00000000000..e1c66d4de5e --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert3.out @@ -0,0 +1,373 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert.out b/src/test/isolation/expected/ivm-refresh-insert.out new file mode 100644 index 00000000000..a925938bf1c --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert.out @@ -0,0 +1,213 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert2.out b/src/test/isolation/expected/ivm-refresh-insert2.out new file mode 100644 index 00000000000..dc1b16ae34e --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert2.out @@ -0,0 +1,191 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert3.out b/src/test/isolation/expected/ivm-refresh-insert3.out new file mode 100644 index 00000000000..dc1b16ae34e --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert3.out @@ -0,0 +1,191 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/isolation_schedule b/src/test/isolation/isolation_schedule index b8ebe92553c..6b7e873b370 100644 --- a/src/test/isolation/isolation_schedule +++ b/src/test/isolation/isolation_schedule @@ -128,3 +128,12 @@ test: matview-write-skew test: lock-nowait test: for-portion-of test: ddl-dependency-locking +test: ivm-create-insert +test: ivm-create-insert2 +test: ivm-create-insert3 +test: ivm-insert-insert +test: ivm-insert-insert2 +test: ivm-insert-insert3 +test: ivm-refresh-insert +test: ivm-refresh-insert2 +test: ivm-refresh-insert3 diff --git a/src/test/isolation/specs/ivm-create-insert.spec b/src/test/isolation/specs/ivm-create-insert.spec new file mode 100644 index 00000000000..ccd6fd080a9 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert.spec @@ -0,0 +1,47 @@ +# Test interaction between concurrent transactions performing +# create and insert in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-create-insert2.spec b/src/test/isolation/specs/ivm-create-insert2.spec new file mode 100644 index 00000000000..02cec85ae07 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert2.spec @@ -0,0 +1,54 @@ +# Test interaction between concurrent transactions performing +# create and insert in REPEATABLE READ isolation level +# +# Note: +# In this isolation level, it is possible that create_immv could +# create an inconsistent view not including effects of a concurrent +# transaction. So, an warning message is raised to suggest using it +# in READ COMMITTED or executing refresh_immv to make sure to +# make the view contents consistent. + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-create-insert3.spec b/src/test/isolation/specs/ivm-create-insert3.spec new file mode 100644 index 00000000000..19ce03185a4 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert3.spec @@ -0,0 +1,54 @@ +# Test interaction between concurrent transactions performing +# create and insert in SERIALIZABLE isolation level +# +# Note: +# In this isolation level, it is possible that create_immv could +# create an inconsistent view not including effects of a concurrent +# transaction. So, an warning message is raised to suggest using it +# in READ COMMITTED or executing refresh_immv to make sure to +# make the view contents consistent. + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert.spec b/src/test/isolation/specs/ivm-insert-insert.spec new file mode 100644 index 00000000000..b8f794ca191 --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert2.spec b/src/test/isolation/specs/ivm-insert-insert2.spec new file mode 100644 index 00000000000..ed086d1ba1e --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert2.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in REPEATABLE READ isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert3.spec b/src/test/isolation/specs/ivm-insert-insert3.spec new file mode 100644 index 00000000000..b18bd121033 --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert3.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in SERIALIZABLE isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert.spec b/src/test/isolation/specs/ivm-refresh-insert.spec new file mode 100644 index 00000000000..d7181251962 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert2.spec b/src/test/isolation/specs/ivm-refresh-insert2.spec new file mode 100644 index 00000000000..f2d1d5013f2 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert2.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in REPEATABLE READ isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert3.spec b/src/test/isolation/specs/ivm-refresh-insert3.spec new file mode 100644 index 00000000000..0ec2b1d1de0 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert3.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in SERIALIZABLE isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/regress/expected/incremental_matview.out b/src/test/regress/expected/incremental_matview.out new file mode 100644 index 00000000000..f215aa88e48 --- /dev/null +++ b/src/test/regress/expected/incremental_matview.out @@ -0,0 +1,1100 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ERROR: materialized view "mv_ivm_1" has not been populated +HINT: Use the REFRESH MATERIALIZED VIEW command. +REFRESH MATERIALIZED VIEW mv_ivm_1; +NOTICE: could not create an index on materialized view "mv_ivm_1" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 17 +(1 row) + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 1 +(1 row) + +ROLLBACK; +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_rename_index" on materialized view "mv_ivm_rename" +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +ERROR: IVM column can not be renamed +DROP MATERIALIZED VIEW mv_ivm_rename; +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_unique_index" on materialized view "mv_ivm_unique" +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +ERROR: unique index creation on IVM columns is not supported +DROP MATERIALIZED VIEW mv_ivm_unique; +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +NOTICE: could not create an index on materialized view "mv_ivm_func" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +NOTICE: could not create an index on materialized view "mv_ivm_no_tbl" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_duplicate" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +NOTICE: created index "mv_ivm_distinct_index" on materialized view "mv_ivm_distinct" +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 20 + 30 + 40 + 50 +(6 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +ROLLBACK; +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 120 | 2 | 60.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+---------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 220 | 2 | 110.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 20 | 1 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 120 | 2 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; + sum | count +-----+------- +(0 rows) + +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; + i | sum | count +---+-----+------- +(0 rows) + +ROLLBACK; +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 150 | 5 | 30.0000000000000000 +(1 row) + +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 210 | 6 | 35.0000000000000000 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +NOTICE: created index "mv_ivm_avg_bug_index" on materialized view "mv_ivm_avg_bug" +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 3 | 3.3333333333333333 + 2 | 80 | 3 | 26.6666666666666667 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_min_max_index" on materialized view "mv_ivm_min_max" +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 10 + 2 | 20 | 20 + 3 | 30 | 30 + 4 | 40 | 40 + 5 | 50 | 50 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 12 + 2 | 20 | 22 + 3 | 30 | 32 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 11 | 12 + 2 | 20 | 22 + 3 | 30 | 31 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min_max" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 50 +(1 row) + +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 0 | 70 +(1 row) + +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 60 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + | +(1 row) + +ROLLBACK; +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min; + min +----- + 10 +(1 row) + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + min +----- + 20 +(1 row) + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; + min +----- + 30 +(1 row) + +ROLLBACK; +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | sum +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | b +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ERROR: too many column names were specified +ROLLBACK; +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +NOTICE: could not create an index on materialized view "mv_self" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +----+---- + 10 | 10 + 20 | 20 + 30 | 30 +(3 rows) + +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 30 | 30 + 40 | 40 + 200 | 200 +(3 rows) + +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 130 | 130 + 300 | 300 +(4 rows) + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 70 | 70 + 70 | 77 + 77 | 70 + 77 | 77 + 130 | 130 + 300 | 300 +(8 rows) + +ROLLBACK; +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY v1; + v1 | v2 +----+----- + 10 | 100 + 20 | 200 + 30 | 300 +(3 rows) + +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv ORDER BY v1; + v1 | v2 +------+----- + 10 | 100 + 11 | 100 + 1020 | 200 + 1020 | 222 +(4 rows) + +ROLLBACK; +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +NOTICE: created index "mv_ri_index" on materialized view "mv_ri" +SELECT * FROM mv_ri ORDER BY i1; + i1 | i2 +----+---- + 1 | 1 + 2 | 2 + 3 | 3 +(3 rows) + +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; + i1 | i2 +----+---- + 3 | 3 + 10 | 10 +(2 rows) + +ROLLBACK; +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | +(2 rows) + +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | 20 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i +--- +(0 rows) + +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; + i +--- + 1 + +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 30 + | 3 +(2 rows) + +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 300 + | 30 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 1 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 4 +(1 row) + +ROLLBACK; +-- IMMV containing user defined type +BEGIN; +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: return type mytype is only a shell +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: argument type mytype is only a shell +LINE 1: CREATE FUNCTION mytype_out(mytype) + ^ +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +NOTICE: could not create an index on materialized view "mv_mytype" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + x +--- + 1 +(1 row) + +ROLLBACK; +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +ERROR: OUTER JOIN is not supported on incrementally maintainable materialized view +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +ERROR: CTE is not supported on incrementally maintainable materialized view +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +ERROR: ORDER BY clause is not supported on incrementally maintainable materialized view +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; +ERROR: HAVING clause is not supported on incrementally maintainable materialized view +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; +ERROR: mutable function is not supported on incrementally maintainable materialized view +HINT: functions must be marked IMMUTABLE +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; +ERROR: LIMIT/OFFSET clause is not supported on incrementally maintainable materialized view +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; +ERROR: DISTINCT ON is not supported on incrementally maintainable materialized view +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); +ERROR: TABLESAMPLE clause is not supported on incrementally maintainable materialized view +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; +ERROR: window functions are not supported on incrementally maintainable materialized view +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +ERROR: aggregate function with FILTER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +ERROR: aggregate function with DISTINCT arguments is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +ERROR: aggregate function with ORDER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); +ERROR: GROUPING SETS, ROLLUP, or CUBE clauses is not supported on incrementally maintainable materialized view +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ERROR: inheritance parent is not supported on incrementally maintainable materialized view +ROLLBACK; +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; +ERROR: UNION/INTERSECT/EXCEPT statements are not supported on incrementally maintainable materialized view +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; +ERROR: empty target list is not supported on incrementally maintainable materialized view +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; +ERROR: FOR UPDATE/SHARE clause is not supported on incrementally maintainable materialized view +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; +ERROR: column name __ivm_count__ is not supported on incrementally maintainable materialized view +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; +ERROR: GROUP BY expression not appearing in select list is not supported on incrementally maintainable materialized view +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); +ERROR: VALUES is not supported on incrementally maintainable materialized view +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +NOTICE: role "regress_ivm_admin" does not exist, skipping +DROP USER IF EXISTS regress_ivm_user; +NOTICE: role "regress_ivm_user" does not exist, skipping +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +NOTICE: could not create an index on materialized view "ivm_rls" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user +(1 row) + +RESET SESSION AUTHORIZATION; +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user + 3 | baz | regress_ivm_user +(2 rows) + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +-- +(1 row) + +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+-------+------------------ + 2 | bar | regress_ivm_user + 3 | baz | regress_ivm_user + 6 | corge | regress_ivm_user +(3 rows) + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +NOTICE: could not create an index on materialized view "ivm_rls2" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +RESET SESSION AUTHORIZATION; +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +-- +(1 row) + +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + id | data | owner | num +----+-------+------------------+--------- + 2 | bar | regress_ivm_user | two + 3 | baz_2 | regress_ivm_user | three_2 + 6 | corge | regress_ivm_user | six +(3 rows) + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +NOTICE: could not create an index on materialized view "mv_update_same" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + i +--- + 2 +(1 row) + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +NOTICE: created index "mv_self_ref_index" on materialized view "mv_self_ref" +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; + a | b +----+---- + 11 | + 12 | 11 + 13 | 12 +(3 rows) + +ROLLBACK; +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; +NOTICE: created index "mv_idx1_index" on materialized view "mv_idx1" +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; +NOTICE: created index "mv_idx2_index" on materialized view "mv_idx2" +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; +NOTICE: created index "mv_idx3_index" on materialized view "mv_idx3" +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +NOTICE: could not create an index on materialized view "mv_idx4" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; +NOTICE: could not create an index on materialized view "mv_idx5" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); +NOTICE: could not create an index on materialized view "mv_idx6" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ERROR: data type json has no default operator class for access method "btree" +ROLLBACK; +-- cleanup +DROP TABLE rls_tbl CASCADE; +NOTICE: drop cascades to 2 other objects +DETAIL: drop cascades to materialized view ivm_rls +drop cascades to materialized view ivm_rls2 +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; +DROP TABLE mv_base_b CASCADE; +NOTICE: drop cascades to 3 other objects +DETAIL: drop cascades to materialized view mv_ivm_1 +drop cascades to view b_view +drop cascades to materialized view b_mview +DROP TABLE mv_base_a CASCADE; diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index 8fa0a6c47fb..7caca5f64fd 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -77,6 +77,7 @@ test: brin_bloom brin_multi # Another group of parallel tests # ---------- test: create_table_like alter_generic alter_operator misc async dbsize merge misc_functions nls sysviews tsrf tid tidscan tidrangescan collate.utf8 collate.icu.utf8 incremental_sort create_role without_overlaps generated_virtual +test: incremental_matview # collate.linux.utf8 and collate.icu.utf8 tests cannot be run in parallel with each other # psql depends on create_am diff --git a/src/test/regress/sql/incremental_matview.sql b/src/test/regress/sql/incremental_matview.sql new file mode 100644 index 00000000000..2d55c393d6f --- /dev/null +++ b/src/test/regress/sql/incremental_matview.sql @@ -0,0 +1,580 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); + +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +REFRESH MATERIALIZED VIEW mv_ivm_1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; + +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; +ROLLBACK; + +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +DROP MATERIALIZED VIEW mv_ivm_rename; + +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +DROP MATERIALIZED VIEW mv_ivm_unique; + +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; + + +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +ROLLBACK; + +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +ROLLBACK; + +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +ROLLBACK; + +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +ROLLBACK; + +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +ROLLBACK; + +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min; + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); + +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; +ROLLBACK; + +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +SELECT * FROM mv_self ORDER BY v1; +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; +SELECT * FROM mv_self ORDER BY v1; + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + +ROLLBACK; + +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +SELECT * FROM mv ORDER BY v1; +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; +SELECT * FROM mv ORDER BY v1; +ROLLBACK; + +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +SELECT * FROM mv_ri ORDER BY i1; +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; +ROLLBACK; + +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +-- IMMV containing user defined type +BEGIN; + +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); + +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; + +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); + +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); + +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + +ROLLBACK; + +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; + +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; + +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; + +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; + +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; + +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); + +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; + +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); + +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ROLLBACK; + +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; + +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; + +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; + +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; + +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; + +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; + +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); + +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +DROP USER IF EXISTS regress_ivm_user; +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; + +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); + +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; + +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; + +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; +RESET SESSION AUTHORIZATION; + +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +RESET SESSION AUTHORIZATION; + +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; +ROLLBACK; + +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); + +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; + +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; + +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; + +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; + +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); + +ROLLBACK; + +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ROLLBACK; + +-- cleanup + +DROP TABLE rls_tbl CASCADE; +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; + +DROP TABLE mv_base_b CASCADE; +DROP TABLE mv_base_a CASCADE; -- 2.43.0 --Multipart=_Wed__1_Jul_2026_00_04_01_+0900_OVSy2WWK_9aByzDJ Content-Type: text/x-diff; name="v38-0009-Add-support-for-min-max-aggregates-for-IVM.patch" Content-Disposition: attachment; filename="v38-0009-Add-support-for-min-max-aggregates-for-IVM.patch" Content-Transfer-Encoding: 7bit ^ permalink raw reply [nested|flat] 78+ messages in thread
* [PATCH v39 7/8] Add regression tests for Incremental View Maintenance @ 2026-05-29 09:31 Yugo Nagata <[email protected]> 0 siblings, 0 replies; 78+ messages in thread From: Yugo Nagata @ 2026-05-29 09:31 UTC (permalink / raw) --- .../isolation/expected/ivm-create-insert.out | 285 ++++++++ .../isolation/expected/ivm-create-insert2.out | 305 ++++++++ .../isolation/expected/ivm-create-insert3.out | 305 ++++++++ .../isolation/expected/ivm-insert-insert.out | 497 +++++++++++++ .../isolation/expected/ivm-insert-insert2.out | 373 ++++++++++ .../isolation/expected/ivm-insert-insert3.out | 373 ++++++++++ .../isolation/expected/ivm-refresh-insert.out | 213 ++++++ .../expected/ivm-refresh-insert2.out | 191 +++++ .../expected/ivm-refresh-insert3.out | 191 +++++ src/test/isolation/isolation_schedule | 9 + .../isolation/specs/ivm-create-insert.spec | 47 ++ .../isolation/specs/ivm-create-insert2.spec | 54 ++ .../isolation/specs/ivm-create-insert3.spec | 54 ++ .../isolation/specs/ivm-insert-insert.spec | 62 ++ .../isolation/specs/ivm-insert-insert2.spec | 62 ++ .../isolation/specs/ivm-insert-insert3.spec | 62 ++ .../isolation/specs/ivm-refresh-insert.spec | 46 ++ .../isolation/specs/ivm-refresh-insert2.spec | 46 ++ .../isolation/specs/ivm-refresh-insert3.spec | 46 ++ .../regress/expected/incremental_matview.out | 667 ++++++++++++++++++ src/test/regress/parallel_schedule | 1 + src/test/regress/sql/incremental_matview.sql | 407 +++++++++++ 22 files changed, 4296 insertions(+) create mode 100644 src/test/isolation/expected/ivm-create-insert.out create mode 100644 src/test/isolation/expected/ivm-create-insert2.out create mode 100644 src/test/isolation/expected/ivm-create-insert3.out create mode 100644 src/test/isolation/expected/ivm-insert-insert.out create mode 100644 src/test/isolation/expected/ivm-insert-insert2.out create mode 100644 src/test/isolation/expected/ivm-insert-insert3.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert2.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert3.out create mode 100644 src/test/isolation/specs/ivm-create-insert.spec create mode 100644 src/test/isolation/specs/ivm-create-insert2.spec create mode 100644 src/test/isolation/specs/ivm-create-insert3.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert2.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert3.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert2.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert3.spec create mode 100644 src/test/regress/expected/incremental_matview.out create mode 100644 src/test/regress/sql/incremental_matview.sql diff --git a/src/test/isolation/expected/ivm-create-insert.out b/src/test/isolation/expected/ivm-create-insert.out new file mode 100644 index 00000000000..5da00043aba --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert.out @@ -0,0 +1,285 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-create-insert2.out b/src/test/isolation/expected/ivm-create-insert2.out new file mode 100644 index 00000000000..907d892c6d4 --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert2.out @@ -0,0 +1,305 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + diff --git a/src/test/isolation/expected/ivm-create-insert3.out b/src/test/isolation/expected/ivm-create-insert3.out new file mode 100644 index 00000000000..907d892c6d4 --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert3.out @@ -0,0 +1,305 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert.out b/src/test/isolation/expected/ivm-insert-insert.out new file mode 100644 index 00000000000..5ca4cfea677 --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert.out @@ -0,0 +1,497 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; <waiting ...> +step c1: COMMIT; +step update2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; <waiting ...> +step c1: COMMIT; +step update2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; <waiting ...> +step c2: COMMIT; +step update1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; <waiting ...> +step c2: COMMIT; +step update1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); <waiting ...> +step c1: COMMIT; +step insert2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); <waiting ...> +step c1: COMMIT; +step insert2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); <waiting ...> +step c2: COMMIT; +step insert1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); <waiting ...> +step c2: COMMIT; +step insert1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert2.out b/src/test/isolation/expected/ivm-insert-insert2.out new file mode 100644 index 00000000000..e1c66d4de5e --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert2.out @@ -0,0 +1,373 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert3.out b/src/test/isolation/expected/ivm-insert-insert3.out new file mode 100644 index 00000000000..e1c66d4de5e --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert3.out @@ -0,0 +1,373 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert.out b/src/test/isolation/expected/ivm-refresh-insert.out new file mode 100644 index 00000000000..a925938bf1c --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert.out @@ -0,0 +1,213 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert2.out b/src/test/isolation/expected/ivm-refresh-insert2.out new file mode 100644 index 00000000000..dc1b16ae34e --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert2.out @@ -0,0 +1,191 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert3.out b/src/test/isolation/expected/ivm-refresh-insert3.out new file mode 100644 index 00000000000..dc1b16ae34e --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert3.out @@ -0,0 +1,191 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/isolation_schedule b/src/test/isolation/isolation_schedule index b8ebe92553c..6b7e873b370 100644 --- a/src/test/isolation/isolation_schedule +++ b/src/test/isolation/isolation_schedule @@ -128,3 +128,12 @@ test: matview-write-skew test: lock-nowait test: for-portion-of test: ddl-dependency-locking +test: ivm-create-insert +test: ivm-create-insert2 +test: ivm-create-insert3 +test: ivm-insert-insert +test: ivm-insert-insert2 +test: ivm-insert-insert3 +test: ivm-refresh-insert +test: ivm-refresh-insert2 +test: ivm-refresh-insert3 diff --git a/src/test/isolation/specs/ivm-create-insert.spec b/src/test/isolation/specs/ivm-create-insert.spec new file mode 100644 index 00000000000..ccd6fd080a9 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert.spec @@ -0,0 +1,47 @@ +# Test interaction between concurrent transactions performing +# create and insert in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-create-insert2.spec b/src/test/isolation/specs/ivm-create-insert2.spec new file mode 100644 index 00000000000..02cec85ae07 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert2.spec @@ -0,0 +1,54 @@ +# Test interaction between concurrent transactions performing +# create and insert in REPEATABLE READ isolation level +# +# Note: +# In this isolation level, it is possible that create_immv could +# create an inconsistent view not including effects of a concurrent +# transaction. So, an warning message is raised to suggest using it +# in READ COMMITTED or executing refresh_immv to make sure to +# make the view contents consistent. + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-create-insert3.spec b/src/test/isolation/specs/ivm-create-insert3.spec new file mode 100644 index 00000000000..19ce03185a4 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert3.spec @@ -0,0 +1,54 @@ +# Test interaction between concurrent transactions performing +# create and insert in SERIALIZABLE isolation level +# +# Note: +# In this isolation level, it is possible that create_immv could +# create an inconsistent view not including effects of a concurrent +# transaction. So, an warning message is raised to suggest using it +# in READ COMMITTED or executing refresh_immv to make sure to +# make the view contents consistent. + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert.spec b/src/test/isolation/specs/ivm-insert-insert.spec new file mode 100644 index 00000000000..b8f794ca191 --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert2.spec b/src/test/isolation/specs/ivm-insert-insert2.spec new file mode 100644 index 00000000000..ed086d1ba1e --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert2.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in REPEATABLE READ isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert3.spec b/src/test/isolation/specs/ivm-insert-insert3.spec new file mode 100644 index 00000000000..b18bd121033 --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert3.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in SERIALIZABLE isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert.spec b/src/test/isolation/specs/ivm-refresh-insert.spec new file mode 100644 index 00000000000..d7181251962 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert2.spec b/src/test/isolation/specs/ivm-refresh-insert2.spec new file mode 100644 index 00000000000..f2d1d5013f2 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert2.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in REPEATABLE READ isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert3.spec b/src/test/isolation/specs/ivm-refresh-insert3.spec new file mode 100644 index 00000000000..0ec2b1d1de0 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert3.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in SERIALIZABLE isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/regress/expected/incremental_matview.out b/src/test/regress/expected/incremental_matview.out new file mode 100644 index 00000000000..c7fd19fdca3 --- /dev/null +++ b/src/test/regress/expected/incremental_matview.out @@ -0,0 +1,667 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ERROR: materialized view "mv_ivm_1" has not been populated +HINT: Use the REFRESH MATERIALIZED VIEW command. +REFRESH MATERIALIZED VIEW mv_ivm_1; +NOTICE: could not create an index on materialized view "mv_ivm_1" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 17 +(1 row) + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 1 +(1 row) + +ROLLBACK; +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- DISTINCT not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT * FROM mv_base_a; +ERROR: DISTINCT is not supported on incrementally maintainable materialized view +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +NOTICE: could not create an index on materialized view "mv_ivm_func" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +NOTICE: could not create an index on materialized view "mv_ivm_no_tbl" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- result of materialized view have duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_duplicate" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 20 + 30 + 40 + 50 +(6 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +ROLLBACK; +-- aggregate not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +ERROR: aggregate function is not supported on incrementally maintainable materialized view +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +NOTICE: could not create an index on materialized view "mv_self" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +----+---- + 10 | 10 + 20 | 20 + 30 | 30 +(3 rows) + +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 30 | 30 + 40 | 40 + 200 | 200 +(3 rows) + +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 130 | 130 + 300 | 300 +(4 rows) + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 70 | 70 + 70 | 77 + 77 | 70 + 77 | 77 + 130 | 130 + 300 | 300 +(8 rows) + +ROLLBACK; +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY v1; + v1 | v2 +----+----- + 10 | 100 + 20 | 200 + 30 | 300 +(3 rows) + +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv ORDER BY v1; + v1 | v2 +------+----- + 10 | 100 + 11 | 100 + 1020 | 200 + 1020 | 222 +(4 rows) + +ROLLBACK; +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +NOTICE: created index "mv_ri_index" on materialized view "mv_ri" +SELECT * FROM mv_ri ORDER BY i1; + i1 | i2 +----+---- + 1 | 1 + 2 | 2 + 3 | 3 +(3 rows) + +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; + i1 | i2 +----+---- + 3 | 3 + 10 | 10 +(2 rows) + +ROLLBACK; +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | +(2 rows) + +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | 20 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i +--- +(0 rows) + +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; + i +--- + 1 + +(2 rows) + +ROLLBACK; +-- IMMV containing user defined type +BEGIN; +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: return type mytype is only a shell +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: argument type mytype is only a shell +LINE 1: CREATE FUNCTION mytype_out(mytype) + ^ +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +NOTICE: could not create an index on materialized view "mv_mytype" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + x +--- + 1 +(1 row) + +ROLLBACK; +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +ERROR: OUTER JOIN is not supported on incrementally maintainable materialized view +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +ERROR: CTE is not supported on incrementally maintainable materialized view +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +ERROR: ORDER BY clause is not supported on incrementally maintainable materialized view +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; +ERROR: HAVING clause is not supported on incrementally maintainable materialized view +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; +ERROR: mutable function is not supported on incrementally maintainable materialized view +HINT: functions must be marked IMMUTABLE +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; +ERROR: LIMIT/OFFSET clause is not supported on incrementally maintainable materialized view +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; +ERROR: DISTINCT is not supported on incrementally maintainable materialized view +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); +ERROR: TABLESAMPLE clause is not supported on incrementally maintainable materialized view +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; +ERROR: window functions are not supported on incrementally maintainable materialized view +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ERROR: inheritance parent is not supported on incrementally maintainable materialized view +ROLLBACK; +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; +ERROR: UNION/INTERSECT/EXCEPT statements are not supported on incrementally maintainable materialized view +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; +ERROR: empty target list is not supported on incrementally maintainable materialized view +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; +ERROR: FOR UPDATE/SHARE clause is not supported on incrementally maintainable materialized view +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; +ERROR: column name __ivm_count__ is not supported on incrementally maintainable materialized view +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; +ERROR: aggregate function is not supported on incrementally maintainable materialized view +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); +ERROR: VALUES is not supported on incrementally maintainable materialized view +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +NOTICE: role "regress_ivm_admin" does not exist, skipping +DROP USER IF EXISTS regress_ivm_user; +NOTICE: role "regress_ivm_user" does not exist, skipping +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +NOTICE: could not create an index on materialized view "ivm_rls" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user +(1 row) + +RESET SESSION AUTHORIZATION; +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user + 3 | baz | regress_ivm_user +(2 rows) + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +-- +(1 row) + +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+-------+------------------ + 2 | bar | regress_ivm_user + 3 | baz | regress_ivm_user + 6 | corge | regress_ivm_user +(3 rows) + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +NOTICE: could not create an index on materialized view "ivm_rls2" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +RESET SESSION AUTHORIZATION; +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +-- +(1 row) + +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + id | data | owner | num +----+-------+------------------+--------- + 2 | bar | regress_ivm_user | two + 3 | baz_2 | regress_ivm_user | three_2 + 6 | corge | regress_ivm_user | six +(3 rows) + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +NOTICE: could not create an index on materialized view "mv_update_same" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + i +--- + 2 +(1 row) + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +NOTICE: created index "mv_self_ref_index" on materialized view "mv_self_ref" +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; + a | b +----+---- + 11 | + 12 | 11 + 13 | 12 +(3 rows) + +ROLLBACK; +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; +NOTICE: created index "mv_idx3_index" on materialized view "mv_idx3" +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +NOTICE: could not create an index on materialized view "mv_idx4" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; +NOTICE: could not create an index on materialized view "mv_idx5" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); +NOTICE: could not create an index on materialized view "mv_idx6" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ERROR: data type json has no default operator class for access method "btree" +ROLLBACK; +-- cleanup +DROP TABLE rls_tbl CASCADE; +NOTICE: drop cascades to 2 other objects +DETAIL: drop cascades to materialized view ivm_rls +drop cascades to materialized view ivm_rls2 +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; +DROP TABLE mv_base_b CASCADE; +NOTICE: drop cascades to 3 other objects +DETAIL: drop cascades to materialized view mv_ivm_1 +drop cascades to view b_view +drop cascades to materialized view b_mview +DROP TABLE mv_base_a CASCADE; diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index 8fa0a6c47fb..7caca5f64fd 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -77,6 +77,7 @@ test: brin_bloom brin_multi # Another group of parallel tests # ---------- test: create_table_like alter_generic alter_operator misc async dbsize merge misc_functions nls sysviews tsrf tid tidscan tidrangescan collate.utf8 collate.icu.utf8 incremental_sort create_role without_overlaps generated_virtual +test: incremental_matview # collate.linux.utf8 and collate.icu.utf8 tests cannot be run in parallel with each other # psql depends on create_am diff --git a/src/test/regress/sql/incremental_matview.sql b/src/test/regress/sql/incremental_matview.sql new file mode 100644 index 00000000000..7313ad82f3e --- /dev/null +++ b/src/test/regress/sql/incremental_matview.sql @@ -0,0 +1,407 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); + +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +REFRESH MATERIALIZED VIEW mv_ivm_1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; + +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; +ROLLBACK; + +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- DISTINCT not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT * FROM mv_base_a; + +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; + + +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +ROLLBACK; + +-- result of materialized view have duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +ROLLBACK; + +-- aggregate not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; + +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +SELECT * FROM mv_self ORDER BY v1; +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; +SELECT * FROM mv_self ORDER BY v1; + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + +ROLLBACK; + +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +SELECT * FROM mv ORDER BY v1; +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; +SELECT * FROM mv ORDER BY v1; +ROLLBACK; + +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +SELECT * FROM mv_ri ORDER BY i1; +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; +ROLLBACK; + +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +-- IMMV containing user defined type +BEGIN; + +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); + +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; + +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); + +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); + +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + +ROLLBACK; + +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; + +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; + +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; + +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; + +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; + +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); + +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; + +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ROLLBACK; + +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; + +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; + +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; + +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; + +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; + +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); + +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +DROP USER IF EXISTS regress_ivm_user; +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; + +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); + +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; + +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; + +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; +RESET SESSION AUTHORIZATION; + +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +RESET SESSION AUTHORIZATION; + +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; +ROLLBACK; + +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); + +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; + +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; + +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); + +ROLLBACK; + +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ROLLBACK; + +-- cleanup + +DROP TABLE rls_tbl CASCADE; +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; + +DROP TABLE mv_base_b CASCADE; +DROP TABLE mv_base_a CASCADE; -- 2.43.0 --Multipart=_Fri__3_Jul_2026_19_11_16_+0900_CskxSIu_iGcDMEyM Content-Type: text/x-diff; name="v39-0006-Add-Incremental-View-Maintenance-support.patch" Content-Disposition: attachment; filename="v39-0006-Add-Incremental-View-Maintenance-support.patch" Content-Transfer-Encoding: 7bit ^ permalink raw reply [nested|flat] 78+ messages in thread
* [PATCH v39 7/8] Add regression tests for Incremental View Maintenance @ 2026-05-29 09:31 Yugo Nagata <[email protected]> 0 siblings, 0 replies; 78+ messages in thread From: Yugo Nagata @ 2026-05-29 09:31 UTC (permalink / raw) --- .../isolation/expected/ivm-create-insert.out | 285 ++++++++ .../isolation/expected/ivm-create-insert2.out | 305 ++++++++ .../isolation/expected/ivm-create-insert3.out | 305 ++++++++ .../isolation/expected/ivm-insert-insert.out | 497 +++++++++++++ .../isolation/expected/ivm-insert-insert2.out | 373 ++++++++++ .../isolation/expected/ivm-insert-insert3.out | 373 ++++++++++ .../isolation/expected/ivm-refresh-insert.out | 213 ++++++ .../expected/ivm-refresh-insert2.out | 191 +++++ .../expected/ivm-refresh-insert3.out | 191 +++++ src/test/isolation/isolation_schedule | 9 + .../isolation/specs/ivm-create-insert.spec | 47 ++ .../isolation/specs/ivm-create-insert2.spec | 54 ++ .../isolation/specs/ivm-create-insert3.spec | 54 ++ .../isolation/specs/ivm-insert-insert.spec | 62 ++ .../isolation/specs/ivm-insert-insert2.spec | 62 ++ .../isolation/specs/ivm-insert-insert3.spec | 62 ++ .../isolation/specs/ivm-refresh-insert.spec | 46 ++ .../isolation/specs/ivm-refresh-insert2.spec | 46 ++ .../isolation/specs/ivm-refresh-insert3.spec | 46 ++ .../regress/expected/incremental_matview.out | 667 ++++++++++++++++++ src/test/regress/parallel_schedule | 1 + src/test/regress/sql/incremental_matview.sql | 407 +++++++++++ 22 files changed, 4296 insertions(+) create mode 100644 src/test/isolation/expected/ivm-create-insert.out create mode 100644 src/test/isolation/expected/ivm-create-insert2.out create mode 100644 src/test/isolation/expected/ivm-create-insert3.out create mode 100644 src/test/isolation/expected/ivm-insert-insert.out create mode 100644 src/test/isolation/expected/ivm-insert-insert2.out create mode 100644 src/test/isolation/expected/ivm-insert-insert3.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert2.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert3.out create mode 100644 src/test/isolation/specs/ivm-create-insert.spec create mode 100644 src/test/isolation/specs/ivm-create-insert2.spec create mode 100644 src/test/isolation/specs/ivm-create-insert3.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert2.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert3.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert2.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert3.spec create mode 100644 src/test/regress/expected/incremental_matview.out create mode 100644 src/test/regress/sql/incremental_matview.sql diff --git a/src/test/isolation/expected/ivm-create-insert.out b/src/test/isolation/expected/ivm-create-insert.out new file mode 100644 index 00000000000..5da00043aba --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert.out @@ -0,0 +1,285 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-create-insert2.out b/src/test/isolation/expected/ivm-create-insert2.out new file mode 100644 index 00000000000..907d892c6d4 --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert2.out @@ -0,0 +1,305 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + diff --git a/src/test/isolation/expected/ivm-create-insert3.out b/src/test/isolation/expected/ivm-create-insert3.out new file mode 100644 index 00000000000..907d892c6d4 --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert3.out @@ -0,0 +1,305 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert.out b/src/test/isolation/expected/ivm-insert-insert.out new file mode 100644 index 00000000000..5ca4cfea677 --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert.out @@ -0,0 +1,497 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; <waiting ...> +step c1: COMMIT; +step update2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; <waiting ...> +step c1: COMMIT; +step update2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; <waiting ...> +step c2: COMMIT; +step update1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; <waiting ...> +step c2: COMMIT; +step update1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); <waiting ...> +step c1: COMMIT; +step insert2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); <waiting ...> +step c1: COMMIT; +step insert2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); <waiting ...> +step c2: COMMIT; +step insert1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); <waiting ...> +step c2: COMMIT; +step insert1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert2.out b/src/test/isolation/expected/ivm-insert-insert2.out new file mode 100644 index 00000000000..e1c66d4de5e --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert2.out @@ -0,0 +1,373 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert3.out b/src/test/isolation/expected/ivm-insert-insert3.out new file mode 100644 index 00000000000..e1c66d4de5e --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert3.out @@ -0,0 +1,373 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert.out b/src/test/isolation/expected/ivm-refresh-insert.out new file mode 100644 index 00000000000..a925938bf1c --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert.out @@ -0,0 +1,213 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert2.out b/src/test/isolation/expected/ivm-refresh-insert2.out new file mode 100644 index 00000000000..dc1b16ae34e --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert2.out @@ -0,0 +1,191 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert3.out b/src/test/isolation/expected/ivm-refresh-insert3.out new file mode 100644 index 00000000000..dc1b16ae34e --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert3.out @@ -0,0 +1,191 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/isolation_schedule b/src/test/isolation/isolation_schedule index b8ebe92553c..6b7e873b370 100644 --- a/src/test/isolation/isolation_schedule +++ b/src/test/isolation/isolation_schedule @@ -128,3 +128,12 @@ test: matview-write-skew test: lock-nowait test: for-portion-of test: ddl-dependency-locking +test: ivm-create-insert +test: ivm-create-insert2 +test: ivm-create-insert3 +test: ivm-insert-insert +test: ivm-insert-insert2 +test: ivm-insert-insert3 +test: ivm-refresh-insert +test: ivm-refresh-insert2 +test: ivm-refresh-insert3 diff --git a/src/test/isolation/specs/ivm-create-insert.spec b/src/test/isolation/specs/ivm-create-insert.spec new file mode 100644 index 00000000000..ccd6fd080a9 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert.spec @@ -0,0 +1,47 @@ +# Test interaction between concurrent transactions performing +# create and insert in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-create-insert2.spec b/src/test/isolation/specs/ivm-create-insert2.spec new file mode 100644 index 00000000000..02cec85ae07 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert2.spec @@ -0,0 +1,54 @@ +# Test interaction between concurrent transactions performing +# create and insert in REPEATABLE READ isolation level +# +# Note: +# In this isolation level, it is possible that create_immv could +# create an inconsistent view not including effects of a concurrent +# transaction. So, an warning message is raised to suggest using it +# in READ COMMITTED or executing refresh_immv to make sure to +# make the view contents consistent. + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-create-insert3.spec b/src/test/isolation/specs/ivm-create-insert3.spec new file mode 100644 index 00000000000..19ce03185a4 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert3.spec @@ -0,0 +1,54 @@ +# Test interaction between concurrent transactions performing +# create and insert in SERIALIZABLE isolation level +# +# Note: +# In this isolation level, it is possible that create_immv could +# create an inconsistent view not including effects of a concurrent +# transaction. So, an warning message is raised to suggest using it +# in READ COMMITTED or executing refresh_immv to make sure to +# make the view contents consistent. + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert.spec b/src/test/isolation/specs/ivm-insert-insert.spec new file mode 100644 index 00000000000..b8f794ca191 --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert2.spec b/src/test/isolation/specs/ivm-insert-insert2.spec new file mode 100644 index 00000000000..ed086d1ba1e --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert2.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in REPEATABLE READ isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert3.spec b/src/test/isolation/specs/ivm-insert-insert3.spec new file mode 100644 index 00000000000..b18bd121033 --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert3.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in SERIALIZABLE isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert.spec b/src/test/isolation/specs/ivm-refresh-insert.spec new file mode 100644 index 00000000000..d7181251962 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert2.spec b/src/test/isolation/specs/ivm-refresh-insert2.spec new file mode 100644 index 00000000000..f2d1d5013f2 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert2.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in REPEATABLE READ isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert3.spec b/src/test/isolation/specs/ivm-refresh-insert3.spec new file mode 100644 index 00000000000..0ec2b1d1de0 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert3.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in SERIALIZABLE isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/regress/expected/incremental_matview.out b/src/test/regress/expected/incremental_matview.out new file mode 100644 index 00000000000..c7fd19fdca3 --- /dev/null +++ b/src/test/regress/expected/incremental_matview.out @@ -0,0 +1,667 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ERROR: materialized view "mv_ivm_1" has not been populated +HINT: Use the REFRESH MATERIALIZED VIEW command. +REFRESH MATERIALIZED VIEW mv_ivm_1; +NOTICE: could not create an index on materialized view "mv_ivm_1" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 17 +(1 row) + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 1 +(1 row) + +ROLLBACK; +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- DISTINCT not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT * FROM mv_base_a; +ERROR: DISTINCT is not supported on incrementally maintainable materialized view +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +NOTICE: could not create an index on materialized view "mv_ivm_func" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +NOTICE: could not create an index on materialized view "mv_ivm_no_tbl" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- result of materialized view have duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_duplicate" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 20 + 30 + 40 + 50 +(6 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +ROLLBACK; +-- aggregate not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +ERROR: aggregate function is not supported on incrementally maintainable materialized view +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +NOTICE: could not create an index on materialized view "mv_self" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +----+---- + 10 | 10 + 20 | 20 + 30 | 30 +(3 rows) + +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 30 | 30 + 40 | 40 + 200 | 200 +(3 rows) + +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 130 | 130 + 300 | 300 +(4 rows) + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 70 | 70 + 70 | 77 + 77 | 70 + 77 | 77 + 130 | 130 + 300 | 300 +(8 rows) + +ROLLBACK; +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY v1; + v1 | v2 +----+----- + 10 | 100 + 20 | 200 + 30 | 300 +(3 rows) + +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv ORDER BY v1; + v1 | v2 +------+----- + 10 | 100 + 11 | 100 + 1020 | 200 + 1020 | 222 +(4 rows) + +ROLLBACK; +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +NOTICE: created index "mv_ri_index" on materialized view "mv_ri" +SELECT * FROM mv_ri ORDER BY i1; + i1 | i2 +----+---- + 1 | 1 + 2 | 2 + 3 | 3 +(3 rows) + +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; + i1 | i2 +----+---- + 3 | 3 + 10 | 10 +(2 rows) + +ROLLBACK; +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | +(2 rows) + +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | 20 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i +--- +(0 rows) + +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; + i +--- + 1 + +(2 rows) + +ROLLBACK; +-- IMMV containing user defined type +BEGIN; +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: return type mytype is only a shell +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: argument type mytype is only a shell +LINE 1: CREATE FUNCTION mytype_out(mytype) + ^ +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +NOTICE: could not create an index on materialized view "mv_mytype" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + x +--- + 1 +(1 row) + +ROLLBACK; +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +ERROR: OUTER JOIN is not supported on incrementally maintainable materialized view +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +ERROR: CTE is not supported on incrementally maintainable materialized view +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +ERROR: ORDER BY clause is not supported on incrementally maintainable materialized view +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; +ERROR: HAVING clause is not supported on incrementally maintainable materialized view +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; +ERROR: mutable function is not supported on incrementally maintainable materialized view +HINT: functions must be marked IMMUTABLE +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; +ERROR: LIMIT/OFFSET clause is not supported on incrementally maintainable materialized view +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; +ERROR: DISTINCT is not supported on incrementally maintainable materialized view +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); +ERROR: TABLESAMPLE clause is not supported on incrementally maintainable materialized view +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; +ERROR: window functions are not supported on incrementally maintainable materialized view +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ERROR: inheritance parent is not supported on incrementally maintainable materialized view +ROLLBACK; +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; +ERROR: UNION/INTERSECT/EXCEPT statements are not supported on incrementally maintainable materialized view +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; +ERROR: empty target list is not supported on incrementally maintainable materialized view +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; +ERROR: FOR UPDATE/SHARE clause is not supported on incrementally maintainable materialized view +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; +ERROR: column name __ivm_count__ is not supported on incrementally maintainable materialized view +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; +ERROR: aggregate function is not supported on incrementally maintainable materialized view +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); +ERROR: VALUES is not supported on incrementally maintainable materialized view +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +NOTICE: role "regress_ivm_admin" does not exist, skipping +DROP USER IF EXISTS regress_ivm_user; +NOTICE: role "regress_ivm_user" does not exist, skipping +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +NOTICE: could not create an index on materialized view "ivm_rls" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user +(1 row) + +RESET SESSION AUTHORIZATION; +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user + 3 | baz | regress_ivm_user +(2 rows) + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +-- +(1 row) + +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+-------+------------------ + 2 | bar | regress_ivm_user + 3 | baz | regress_ivm_user + 6 | corge | regress_ivm_user +(3 rows) + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +NOTICE: could not create an index on materialized view "ivm_rls2" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +RESET SESSION AUTHORIZATION; +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +-- +(1 row) + +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + id | data | owner | num +----+-------+------------------+--------- + 2 | bar | regress_ivm_user | two + 3 | baz_2 | regress_ivm_user | three_2 + 6 | corge | regress_ivm_user | six +(3 rows) + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +NOTICE: could not create an index on materialized view "mv_update_same" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + i +--- + 2 +(1 row) + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +NOTICE: created index "mv_self_ref_index" on materialized view "mv_self_ref" +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; + a | b +----+---- + 11 | + 12 | 11 + 13 | 12 +(3 rows) + +ROLLBACK; +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; +NOTICE: created index "mv_idx3_index" on materialized view "mv_idx3" +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +NOTICE: could not create an index on materialized view "mv_idx4" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; +NOTICE: could not create an index on materialized view "mv_idx5" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); +NOTICE: could not create an index on materialized view "mv_idx6" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ERROR: data type json has no default operator class for access method "btree" +ROLLBACK; +-- cleanup +DROP TABLE rls_tbl CASCADE; +NOTICE: drop cascades to 2 other objects +DETAIL: drop cascades to materialized view ivm_rls +drop cascades to materialized view ivm_rls2 +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; +DROP TABLE mv_base_b CASCADE; +NOTICE: drop cascades to 3 other objects +DETAIL: drop cascades to materialized view mv_ivm_1 +drop cascades to view b_view +drop cascades to materialized view b_mview +DROP TABLE mv_base_a CASCADE; diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index 8fa0a6c47fb..7caca5f64fd 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -77,6 +77,7 @@ test: brin_bloom brin_multi # Another group of parallel tests # ---------- test: create_table_like alter_generic alter_operator misc async dbsize merge misc_functions nls sysviews tsrf tid tidscan tidrangescan collate.utf8 collate.icu.utf8 incremental_sort create_role without_overlaps generated_virtual +test: incremental_matview # collate.linux.utf8 and collate.icu.utf8 tests cannot be run in parallel with each other # psql depends on create_am diff --git a/src/test/regress/sql/incremental_matview.sql b/src/test/regress/sql/incremental_matview.sql new file mode 100644 index 00000000000..7313ad82f3e --- /dev/null +++ b/src/test/regress/sql/incremental_matview.sql @@ -0,0 +1,407 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); + +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +REFRESH MATERIALIZED VIEW mv_ivm_1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; + +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; +ROLLBACK; + +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- DISTINCT not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT * FROM mv_base_a; + +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; + + +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +ROLLBACK; + +-- result of materialized view have duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +ROLLBACK; + +-- aggregate not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; + +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +SELECT * FROM mv_self ORDER BY v1; +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; +SELECT * FROM mv_self ORDER BY v1; + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + +ROLLBACK; + +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +SELECT * FROM mv ORDER BY v1; +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; +SELECT * FROM mv ORDER BY v1; +ROLLBACK; + +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +SELECT * FROM mv_ri ORDER BY i1; +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; +ROLLBACK; + +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +-- IMMV containing user defined type +BEGIN; + +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); + +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; + +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); + +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); + +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + +ROLLBACK; + +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; + +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; + +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; + +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; + +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; + +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); + +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; + +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ROLLBACK; + +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; + +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; + +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; + +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; + +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; + +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); + +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +DROP USER IF EXISTS regress_ivm_user; +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; + +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); + +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; + +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; + +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; +RESET SESSION AUTHORIZATION; + +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +RESET SESSION AUTHORIZATION; + +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; +ROLLBACK; + +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); + +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; + +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; + +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); + +ROLLBACK; + +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ROLLBACK; + +-- cleanup + +DROP TABLE rls_tbl CASCADE; +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; + +DROP TABLE mv_base_b CASCADE; +DROP TABLE mv_base_a CASCADE; -- 2.43.0 --Multipart=_Fri__3_Jul_2026_19_11_16_+0900_CskxSIu_iGcDMEyM Content-Type: text/x-diff; name="v39-0006-Add-Incremental-View-Maintenance-support.patch" Content-Disposition: attachment; filename="v39-0006-Add-Incremental-View-Maintenance-support.patch" Content-Transfer-Encoding: 7bit ^ permalink raw reply [nested|flat] 78+ messages in thread
* [PATCH v38 10/11] Add regression tests for Incremental View Maintenance @ 2026-05-29 09:31 Yugo Nagata <[email protected]> 0 siblings, 0 replies; 78+ messages in thread From: Yugo Nagata @ 2026-05-29 09:31 UTC (permalink / raw) --- .../isolation/expected/ivm-create-insert.out | 285 +++++ .../isolation/expected/ivm-create-insert2.out | 305 +++++ .../isolation/expected/ivm-create-insert3.out | 305 +++++ .../isolation/expected/ivm-insert-insert.out | 497 ++++++++ .../isolation/expected/ivm-insert-insert2.out | 373 ++++++ .../isolation/expected/ivm-insert-insert3.out | 373 ++++++ .../isolation/expected/ivm-refresh-insert.out | 213 ++++ .../expected/ivm-refresh-insert2.out | 191 +++ .../expected/ivm-refresh-insert3.out | 191 +++ src/test/isolation/isolation_schedule | 9 + .../isolation/specs/ivm-create-insert.spec | 47 + .../isolation/specs/ivm-create-insert2.spec | 54 + .../isolation/specs/ivm-create-insert3.spec | 54 + .../isolation/specs/ivm-insert-insert.spec | 62 + .../isolation/specs/ivm-insert-insert2.spec | 62 + .../isolation/specs/ivm-insert-insert3.spec | 62 + .../isolation/specs/ivm-refresh-insert.spec | 46 + .../isolation/specs/ivm-refresh-insert2.spec | 46 + .../isolation/specs/ivm-refresh-insert3.spec | 46 + .../regress/expected/incremental_matview.out | 1100 +++++++++++++++++ src/test/regress/parallel_schedule | 1 + src/test/regress/sql/incremental_matview.sql | 580 +++++++++ 22 files changed, 4902 insertions(+) create mode 100644 src/test/isolation/expected/ivm-create-insert.out create mode 100644 src/test/isolation/expected/ivm-create-insert2.out create mode 100644 src/test/isolation/expected/ivm-create-insert3.out create mode 100644 src/test/isolation/expected/ivm-insert-insert.out create mode 100644 src/test/isolation/expected/ivm-insert-insert2.out create mode 100644 src/test/isolation/expected/ivm-insert-insert3.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert2.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert3.out create mode 100644 src/test/isolation/specs/ivm-create-insert.spec create mode 100644 src/test/isolation/specs/ivm-create-insert2.spec create mode 100644 src/test/isolation/specs/ivm-create-insert3.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert2.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert3.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert2.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert3.spec create mode 100644 src/test/regress/expected/incremental_matview.out create mode 100644 src/test/regress/sql/incremental_matview.sql diff --git a/src/test/isolation/expected/ivm-create-insert.out b/src/test/isolation/expected/ivm-create-insert.out new file mode 100644 index 00000000000..5da00043aba --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert.out @@ -0,0 +1,285 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-create-insert2.out b/src/test/isolation/expected/ivm-create-insert2.out new file mode 100644 index 00000000000..907d892c6d4 --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert2.out @@ -0,0 +1,305 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + diff --git a/src/test/isolation/expected/ivm-create-insert3.out b/src/test/isolation/expected/ivm-create-insert3.out new file mode 100644 index 00000000000..907d892c6d4 --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert3.out @@ -0,0 +1,305 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert.out b/src/test/isolation/expected/ivm-insert-insert.out new file mode 100644 index 00000000000..5ca4cfea677 --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert.out @@ -0,0 +1,497 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; <waiting ...> +step c1: COMMIT; +step update2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; <waiting ...> +step c1: COMMIT; +step update2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; <waiting ...> +step c2: COMMIT; +step update1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; <waiting ...> +step c2: COMMIT; +step update1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); <waiting ...> +step c1: COMMIT; +step insert2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); <waiting ...> +step c1: COMMIT; +step insert2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); <waiting ...> +step c2: COMMIT; +step insert1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); <waiting ...> +step c2: COMMIT; +step insert1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert2.out b/src/test/isolation/expected/ivm-insert-insert2.out new file mode 100644 index 00000000000..e1c66d4de5e --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert2.out @@ -0,0 +1,373 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert3.out b/src/test/isolation/expected/ivm-insert-insert3.out new file mode 100644 index 00000000000..e1c66d4de5e --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert3.out @@ -0,0 +1,373 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert.out b/src/test/isolation/expected/ivm-refresh-insert.out new file mode 100644 index 00000000000..a925938bf1c --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert.out @@ -0,0 +1,213 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert2.out b/src/test/isolation/expected/ivm-refresh-insert2.out new file mode 100644 index 00000000000..dc1b16ae34e --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert2.out @@ -0,0 +1,191 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert3.out b/src/test/isolation/expected/ivm-refresh-insert3.out new file mode 100644 index 00000000000..dc1b16ae34e --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert3.out @@ -0,0 +1,191 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/isolation_schedule b/src/test/isolation/isolation_schedule index b8ebe92553c..6b7e873b370 100644 --- a/src/test/isolation/isolation_schedule +++ b/src/test/isolation/isolation_schedule @@ -128,3 +128,12 @@ test: matview-write-skew test: lock-nowait test: for-portion-of test: ddl-dependency-locking +test: ivm-create-insert +test: ivm-create-insert2 +test: ivm-create-insert3 +test: ivm-insert-insert +test: ivm-insert-insert2 +test: ivm-insert-insert3 +test: ivm-refresh-insert +test: ivm-refresh-insert2 +test: ivm-refresh-insert3 diff --git a/src/test/isolation/specs/ivm-create-insert.spec b/src/test/isolation/specs/ivm-create-insert.spec new file mode 100644 index 00000000000..ccd6fd080a9 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert.spec @@ -0,0 +1,47 @@ +# Test interaction between concurrent transactions performing +# create and insert in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-create-insert2.spec b/src/test/isolation/specs/ivm-create-insert2.spec new file mode 100644 index 00000000000..02cec85ae07 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert2.spec @@ -0,0 +1,54 @@ +# Test interaction between concurrent transactions performing +# create and insert in REPEATABLE READ isolation level +# +# Note: +# In this isolation level, it is possible that create_immv could +# create an inconsistent view not including effects of a concurrent +# transaction. So, an warning message is raised to suggest using it +# in READ COMMITTED or executing refresh_immv to make sure to +# make the view contents consistent. + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-create-insert3.spec b/src/test/isolation/specs/ivm-create-insert3.spec new file mode 100644 index 00000000000..19ce03185a4 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert3.spec @@ -0,0 +1,54 @@ +# Test interaction between concurrent transactions performing +# create and insert in SERIALIZABLE isolation level +# +# Note: +# In this isolation level, it is possible that create_immv could +# create an inconsistent view not including effects of a concurrent +# transaction. So, an warning message is raised to suggest using it +# in READ COMMITTED or executing refresh_immv to make sure to +# make the view contents consistent. + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert.spec b/src/test/isolation/specs/ivm-insert-insert.spec new file mode 100644 index 00000000000..b8f794ca191 --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert2.spec b/src/test/isolation/specs/ivm-insert-insert2.spec new file mode 100644 index 00000000000..ed086d1ba1e --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert2.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in REPEATABLE READ isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert3.spec b/src/test/isolation/specs/ivm-insert-insert3.spec new file mode 100644 index 00000000000..b18bd121033 --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert3.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in SERIALIZABLE isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert.spec b/src/test/isolation/specs/ivm-refresh-insert.spec new file mode 100644 index 00000000000..d7181251962 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert2.spec b/src/test/isolation/specs/ivm-refresh-insert2.spec new file mode 100644 index 00000000000..f2d1d5013f2 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert2.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in REPEATABLE READ isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert3.spec b/src/test/isolation/specs/ivm-refresh-insert3.spec new file mode 100644 index 00000000000..0ec2b1d1de0 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert3.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in SERIALIZABLE isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/regress/expected/incremental_matview.out b/src/test/regress/expected/incremental_matview.out new file mode 100644 index 00000000000..f215aa88e48 --- /dev/null +++ b/src/test/regress/expected/incremental_matview.out @@ -0,0 +1,1100 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ERROR: materialized view "mv_ivm_1" has not been populated +HINT: Use the REFRESH MATERIALIZED VIEW command. +REFRESH MATERIALIZED VIEW mv_ivm_1; +NOTICE: could not create an index on materialized view "mv_ivm_1" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 17 +(1 row) + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 1 +(1 row) + +ROLLBACK; +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_rename_index" on materialized view "mv_ivm_rename" +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +ERROR: IVM column can not be renamed +DROP MATERIALIZED VIEW mv_ivm_rename; +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_unique_index" on materialized view "mv_ivm_unique" +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +ERROR: unique index creation on IVM columns is not supported +DROP MATERIALIZED VIEW mv_ivm_unique; +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +NOTICE: could not create an index on materialized view "mv_ivm_func" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +NOTICE: could not create an index on materialized view "mv_ivm_no_tbl" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_duplicate" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +NOTICE: created index "mv_ivm_distinct_index" on materialized view "mv_ivm_distinct" +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 20 + 30 + 40 + 50 +(6 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +ROLLBACK; +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 120 | 2 | 60.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+---------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 220 | 2 | 110.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 20 | 1 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 120 | 2 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; + sum | count +-----+------- +(0 rows) + +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; + i | sum | count +---+-----+------- +(0 rows) + +ROLLBACK; +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 150 | 5 | 30.0000000000000000 +(1 row) + +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 210 | 6 | 35.0000000000000000 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +NOTICE: created index "mv_ivm_avg_bug_index" on materialized view "mv_ivm_avg_bug" +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 3 | 3.3333333333333333 + 2 | 80 | 3 | 26.6666666666666667 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_min_max_index" on materialized view "mv_ivm_min_max" +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 10 + 2 | 20 | 20 + 3 | 30 | 30 + 4 | 40 | 40 + 5 | 50 | 50 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 12 + 2 | 20 | 22 + 3 | 30 | 32 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 11 | 12 + 2 | 20 | 22 + 3 | 30 | 31 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min_max" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 50 +(1 row) + +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 0 | 70 +(1 row) + +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 60 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + | +(1 row) + +ROLLBACK; +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min; + min +----- + 10 +(1 row) + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + min +----- + 20 +(1 row) + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; + min +----- + 30 +(1 row) + +ROLLBACK; +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | sum +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | b +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ERROR: too many column names were specified +ROLLBACK; +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +NOTICE: could not create an index on materialized view "mv_self" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +----+---- + 10 | 10 + 20 | 20 + 30 | 30 +(3 rows) + +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 30 | 30 + 40 | 40 + 200 | 200 +(3 rows) + +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 130 | 130 + 300 | 300 +(4 rows) + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 70 | 70 + 70 | 77 + 77 | 70 + 77 | 77 + 130 | 130 + 300 | 300 +(8 rows) + +ROLLBACK; +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY v1; + v1 | v2 +----+----- + 10 | 100 + 20 | 200 + 30 | 300 +(3 rows) + +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv ORDER BY v1; + v1 | v2 +------+----- + 10 | 100 + 11 | 100 + 1020 | 200 + 1020 | 222 +(4 rows) + +ROLLBACK; +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +NOTICE: created index "mv_ri_index" on materialized view "mv_ri" +SELECT * FROM mv_ri ORDER BY i1; + i1 | i2 +----+---- + 1 | 1 + 2 | 2 + 3 | 3 +(3 rows) + +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; + i1 | i2 +----+---- + 3 | 3 + 10 | 10 +(2 rows) + +ROLLBACK; +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | +(2 rows) + +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | 20 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i +--- +(0 rows) + +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; + i +--- + 1 + +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 30 + | 3 +(2 rows) + +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 300 + | 30 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 1 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 4 +(1 row) + +ROLLBACK; +-- IMMV containing user defined type +BEGIN; +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: return type mytype is only a shell +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: argument type mytype is only a shell +LINE 1: CREATE FUNCTION mytype_out(mytype) + ^ +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +NOTICE: could not create an index on materialized view "mv_mytype" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + x +--- + 1 +(1 row) + +ROLLBACK; +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +ERROR: OUTER JOIN is not supported on incrementally maintainable materialized view +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +ERROR: CTE is not supported on incrementally maintainable materialized view +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +ERROR: ORDER BY clause is not supported on incrementally maintainable materialized view +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; +ERROR: HAVING clause is not supported on incrementally maintainable materialized view +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; +ERROR: mutable function is not supported on incrementally maintainable materialized view +HINT: functions must be marked IMMUTABLE +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; +ERROR: LIMIT/OFFSET clause is not supported on incrementally maintainable materialized view +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; +ERROR: DISTINCT ON is not supported on incrementally maintainable materialized view +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); +ERROR: TABLESAMPLE clause is not supported on incrementally maintainable materialized view +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; +ERROR: window functions are not supported on incrementally maintainable materialized view +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +ERROR: aggregate function with FILTER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +ERROR: aggregate function with DISTINCT arguments is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +ERROR: aggregate function with ORDER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); +ERROR: GROUPING SETS, ROLLUP, or CUBE clauses is not supported on incrementally maintainable materialized view +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ERROR: inheritance parent is not supported on incrementally maintainable materialized view +ROLLBACK; +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; +ERROR: UNION/INTERSECT/EXCEPT statements are not supported on incrementally maintainable materialized view +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; +ERROR: empty target list is not supported on incrementally maintainable materialized view +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; +ERROR: FOR UPDATE/SHARE clause is not supported on incrementally maintainable materialized view +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; +ERROR: column name __ivm_count__ is not supported on incrementally maintainable materialized view +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; +ERROR: GROUP BY expression not appearing in select list is not supported on incrementally maintainable materialized view +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); +ERROR: VALUES is not supported on incrementally maintainable materialized view +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +NOTICE: role "regress_ivm_admin" does not exist, skipping +DROP USER IF EXISTS regress_ivm_user; +NOTICE: role "regress_ivm_user" does not exist, skipping +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +NOTICE: could not create an index on materialized view "ivm_rls" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user +(1 row) + +RESET SESSION AUTHORIZATION; +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user + 3 | baz | regress_ivm_user +(2 rows) + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +-- +(1 row) + +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+-------+------------------ + 2 | bar | regress_ivm_user + 3 | baz | regress_ivm_user + 6 | corge | regress_ivm_user +(3 rows) + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +NOTICE: could not create an index on materialized view "ivm_rls2" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +RESET SESSION AUTHORIZATION; +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +-- +(1 row) + +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + id | data | owner | num +----+-------+------------------+--------- + 2 | bar | regress_ivm_user | two + 3 | baz_2 | regress_ivm_user | three_2 + 6 | corge | regress_ivm_user | six +(3 rows) + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +NOTICE: could not create an index on materialized view "mv_update_same" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + i +--- + 2 +(1 row) + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +NOTICE: created index "mv_self_ref_index" on materialized view "mv_self_ref" +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; + a | b +----+---- + 11 | + 12 | 11 + 13 | 12 +(3 rows) + +ROLLBACK; +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; +NOTICE: created index "mv_idx1_index" on materialized view "mv_idx1" +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; +NOTICE: created index "mv_idx2_index" on materialized view "mv_idx2" +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; +NOTICE: created index "mv_idx3_index" on materialized view "mv_idx3" +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +NOTICE: could not create an index on materialized view "mv_idx4" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; +NOTICE: could not create an index on materialized view "mv_idx5" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); +NOTICE: could not create an index on materialized view "mv_idx6" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ERROR: data type json has no default operator class for access method "btree" +ROLLBACK; +-- cleanup +DROP TABLE rls_tbl CASCADE; +NOTICE: drop cascades to 2 other objects +DETAIL: drop cascades to materialized view ivm_rls +drop cascades to materialized view ivm_rls2 +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; +DROP TABLE mv_base_b CASCADE; +NOTICE: drop cascades to 3 other objects +DETAIL: drop cascades to materialized view mv_ivm_1 +drop cascades to view b_view +drop cascades to materialized view b_mview +DROP TABLE mv_base_a CASCADE; diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index 8fa0a6c47fb..7caca5f64fd 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -77,6 +77,7 @@ test: brin_bloom brin_multi # Another group of parallel tests # ---------- test: create_table_like alter_generic alter_operator misc async dbsize merge misc_functions nls sysviews tsrf tid tidscan tidrangescan collate.utf8 collate.icu.utf8 incremental_sort create_role without_overlaps generated_virtual +test: incremental_matview # collate.linux.utf8 and collate.icu.utf8 tests cannot be run in parallel with each other # psql depends on create_am diff --git a/src/test/regress/sql/incremental_matview.sql b/src/test/regress/sql/incremental_matview.sql new file mode 100644 index 00000000000..2d55c393d6f --- /dev/null +++ b/src/test/regress/sql/incremental_matview.sql @@ -0,0 +1,580 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); + +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +REFRESH MATERIALIZED VIEW mv_ivm_1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; + +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; +ROLLBACK; + +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +DROP MATERIALIZED VIEW mv_ivm_rename; + +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +DROP MATERIALIZED VIEW mv_ivm_unique; + +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; + + +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +ROLLBACK; + +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +ROLLBACK; + +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +ROLLBACK; + +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +ROLLBACK; + +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +ROLLBACK; + +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min; + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); + +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; +ROLLBACK; + +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +SELECT * FROM mv_self ORDER BY v1; +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; +SELECT * FROM mv_self ORDER BY v1; + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + +ROLLBACK; + +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +SELECT * FROM mv ORDER BY v1; +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; +SELECT * FROM mv ORDER BY v1; +ROLLBACK; + +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +SELECT * FROM mv_ri ORDER BY i1; +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; +ROLLBACK; + +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +-- IMMV containing user defined type +BEGIN; + +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); + +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; + +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); + +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); + +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + +ROLLBACK; + +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; + +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; + +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; + +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; + +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; + +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); + +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; + +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); + +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ROLLBACK; + +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; + +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; + +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; + +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; + +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; + +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; + +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); + +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +DROP USER IF EXISTS regress_ivm_user; +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; + +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); + +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; + +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; + +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; +RESET SESSION AUTHORIZATION; + +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +RESET SESSION AUTHORIZATION; + +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; +ROLLBACK; + +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); + +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; + +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; + +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; + +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; + +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); + +ROLLBACK; + +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ROLLBACK; + +-- cleanup + +DROP TABLE rls_tbl CASCADE; +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; + +DROP TABLE mv_base_b CASCADE; +DROP TABLE mv_base_a CASCADE; -- 2.43.0 --Multipart=_Wed__1_Jul_2026_00_04_01_+0900_OVSy2WWK_9aByzDJ Content-Type: text/x-diff; name="v38-0009-Add-support-for-min-max-aggregates-for-IVM.patch" Content-Disposition: attachment; filename="v38-0009-Add-support-for-min-max-aggregates-for-IVM.patch" Content-Transfer-Encoding: 7bit ^ permalink raw reply [nested|flat] 78+ messages in thread
* [PATCH v37 10/11] Add regression tests for Incremental View Maintenance @ 2026-05-29 09:31 Yugo Nagata <[email protected]> 0 siblings, 0 replies; 78+ messages in thread From: Yugo Nagata @ 2026-05-29 09:31 UTC (permalink / raw) --- src/test/isolation/isolation_schedule | 9 + .../regress/expected/incremental_matview.out | 1100 +++++++++++++++++ src/test/regress/parallel_schedule | 1 + src/test/regress/sql/incremental_matview.sql | 580 +++++++++ 4 files changed, 1690 insertions(+) create mode 100644 src/test/regress/expected/incremental_matview.out create mode 100644 src/test/regress/sql/incremental_matview.sql diff --git a/src/test/isolation/isolation_schedule b/src/test/isolation/isolation_schedule index 15c33fad4c5..111fd465207 100644 --- a/src/test/isolation/isolation_schedule +++ b/src/test/isolation/isolation_schedule @@ -127,3 +127,12 @@ test: matview-write-skew test: lock-nowait test: for-portion-of test: ddl-dependency-locking +test: ivm-create-insert +test: ivm-create-insert2 +test: ivm-create-insert3 +test: ivm-insert-insert +test: ivm-insert-insert2 +test: ivm-insert-insert3 +test: ivm-refresh-insert +test: ivm-refresh-insert2 +test: ivm-refresh-insert3 diff --git a/src/test/regress/expected/incremental_matview.out b/src/test/regress/expected/incremental_matview.out new file mode 100644 index 00000000000..f215aa88e48 --- /dev/null +++ b/src/test/regress/expected/incremental_matview.out @@ -0,0 +1,1100 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ERROR: materialized view "mv_ivm_1" has not been populated +HINT: Use the REFRESH MATERIALIZED VIEW command. +REFRESH MATERIALIZED VIEW mv_ivm_1; +NOTICE: could not create an index on materialized view "mv_ivm_1" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 17 +(1 row) + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 1 +(1 row) + +ROLLBACK; +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_rename_index" on materialized view "mv_ivm_rename" +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +ERROR: IVM column can not be renamed +DROP MATERIALIZED VIEW mv_ivm_rename; +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_unique_index" on materialized view "mv_ivm_unique" +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +ERROR: unique index creation on IVM columns is not supported +DROP MATERIALIZED VIEW mv_ivm_unique; +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +NOTICE: could not create an index on materialized view "mv_ivm_func" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +NOTICE: could not create an index on materialized view "mv_ivm_no_tbl" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_duplicate" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +NOTICE: created index "mv_ivm_distinct_index" on materialized view "mv_ivm_distinct" +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 20 + 30 + 40 + 50 +(6 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +ROLLBACK; +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 120 | 2 | 60.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+---------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 220 | 2 | 110.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 20 | 1 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 120 | 2 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; + sum | count +-----+------- +(0 rows) + +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; + i | sum | count +---+-----+------- +(0 rows) + +ROLLBACK; +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 150 | 5 | 30.0000000000000000 +(1 row) + +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 210 | 6 | 35.0000000000000000 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +NOTICE: created index "mv_ivm_avg_bug_index" on materialized view "mv_ivm_avg_bug" +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 3 | 3.3333333333333333 + 2 | 80 | 3 | 26.6666666666666667 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_min_max_index" on materialized view "mv_ivm_min_max" +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 10 + 2 | 20 | 20 + 3 | 30 | 30 + 4 | 40 | 40 + 5 | 50 | 50 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 12 + 2 | 20 | 22 + 3 | 30 | 32 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 11 | 12 + 2 | 20 | 22 + 3 | 30 | 31 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min_max" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 50 +(1 row) + +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 0 | 70 +(1 row) + +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 60 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + | +(1 row) + +ROLLBACK; +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min; + min +----- + 10 +(1 row) + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + min +----- + 20 +(1 row) + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; + min +----- + 30 +(1 row) + +ROLLBACK; +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | sum +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | b +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ERROR: too many column names were specified +ROLLBACK; +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +NOTICE: could not create an index on materialized view "mv_self" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +----+---- + 10 | 10 + 20 | 20 + 30 | 30 +(3 rows) + +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 30 | 30 + 40 | 40 + 200 | 200 +(3 rows) + +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 130 | 130 + 300 | 300 +(4 rows) + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 70 | 70 + 70 | 77 + 77 | 70 + 77 | 77 + 130 | 130 + 300 | 300 +(8 rows) + +ROLLBACK; +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY v1; + v1 | v2 +----+----- + 10 | 100 + 20 | 200 + 30 | 300 +(3 rows) + +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv ORDER BY v1; + v1 | v2 +------+----- + 10 | 100 + 11 | 100 + 1020 | 200 + 1020 | 222 +(4 rows) + +ROLLBACK; +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +NOTICE: created index "mv_ri_index" on materialized view "mv_ri" +SELECT * FROM mv_ri ORDER BY i1; + i1 | i2 +----+---- + 1 | 1 + 2 | 2 + 3 | 3 +(3 rows) + +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; + i1 | i2 +----+---- + 3 | 3 + 10 | 10 +(2 rows) + +ROLLBACK; +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | +(2 rows) + +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | 20 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i +--- +(0 rows) + +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; + i +--- + 1 + +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 30 + | 3 +(2 rows) + +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 300 + | 30 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 1 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 4 +(1 row) + +ROLLBACK; +-- IMMV containing user defined type +BEGIN; +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: return type mytype is only a shell +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: argument type mytype is only a shell +LINE 1: CREATE FUNCTION mytype_out(mytype) + ^ +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +NOTICE: could not create an index on materialized view "mv_mytype" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + x +--- + 1 +(1 row) + +ROLLBACK; +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +ERROR: OUTER JOIN is not supported on incrementally maintainable materialized view +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +ERROR: CTE is not supported on incrementally maintainable materialized view +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +ERROR: ORDER BY clause is not supported on incrementally maintainable materialized view +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; +ERROR: HAVING clause is not supported on incrementally maintainable materialized view +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; +ERROR: mutable function is not supported on incrementally maintainable materialized view +HINT: functions must be marked IMMUTABLE +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; +ERROR: LIMIT/OFFSET clause is not supported on incrementally maintainable materialized view +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; +ERROR: DISTINCT ON is not supported on incrementally maintainable materialized view +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); +ERROR: TABLESAMPLE clause is not supported on incrementally maintainable materialized view +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; +ERROR: window functions are not supported on incrementally maintainable materialized view +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +ERROR: aggregate function with FILTER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +ERROR: aggregate function with DISTINCT arguments is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +ERROR: aggregate function with ORDER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); +ERROR: GROUPING SETS, ROLLUP, or CUBE clauses is not supported on incrementally maintainable materialized view +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ERROR: inheritance parent is not supported on incrementally maintainable materialized view +ROLLBACK; +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; +ERROR: UNION/INTERSECT/EXCEPT statements are not supported on incrementally maintainable materialized view +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; +ERROR: empty target list is not supported on incrementally maintainable materialized view +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; +ERROR: FOR UPDATE/SHARE clause is not supported on incrementally maintainable materialized view +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; +ERROR: column name __ivm_count__ is not supported on incrementally maintainable materialized view +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; +ERROR: GROUP BY expression not appearing in select list is not supported on incrementally maintainable materialized view +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); +ERROR: VALUES is not supported on incrementally maintainable materialized view +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +NOTICE: role "regress_ivm_admin" does not exist, skipping +DROP USER IF EXISTS regress_ivm_user; +NOTICE: role "regress_ivm_user" does not exist, skipping +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +NOTICE: could not create an index on materialized view "ivm_rls" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user +(1 row) + +RESET SESSION AUTHORIZATION; +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user + 3 | baz | regress_ivm_user +(2 rows) + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +-- +(1 row) + +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+-------+------------------ + 2 | bar | regress_ivm_user + 3 | baz | regress_ivm_user + 6 | corge | regress_ivm_user +(3 rows) + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +NOTICE: could not create an index on materialized view "ivm_rls2" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +RESET SESSION AUTHORIZATION; +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +-- +(1 row) + +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + id | data | owner | num +----+-------+------------------+--------- + 2 | bar | regress_ivm_user | two + 3 | baz_2 | regress_ivm_user | three_2 + 6 | corge | regress_ivm_user | six +(3 rows) + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +NOTICE: could not create an index on materialized view "mv_update_same" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + i +--- + 2 +(1 row) + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +NOTICE: created index "mv_self_ref_index" on materialized view "mv_self_ref" +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; + a | b +----+---- + 11 | + 12 | 11 + 13 | 12 +(3 rows) + +ROLLBACK; +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; +NOTICE: created index "mv_idx1_index" on materialized view "mv_idx1" +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; +NOTICE: created index "mv_idx2_index" on materialized view "mv_idx2" +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; +NOTICE: created index "mv_idx3_index" on materialized view "mv_idx3" +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +NOTICE: could not create an index on materialized view "mv_idx4" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; +NOTICE: could not create an index on materialized view "mv_idx5" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); +NOTICE: could not create an index on materialized view "mv_idx6" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ERROR: data type json has no default operator class for access method "btree" +ROLLBACK; +-- cleanup +DROP TABLE rls_tbl CASCADE; +NOTICE: drop cascades to 2 other objects +DETAIL: drop cascades to materialized view ivm_rls +drop cascades to materialized view ivm_rls2 +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; +DROP TABLE mv_base_b CASCADE; +NOTICE: drop cascades to 3 other objects +DETAIL: drop cascades to materialized view mv_ivm_1 +drop cascades to view b_view +drop cascades to materialized view b_mview +DROP TABLE mv_base_a CASCADE; diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index 8fa0a6c47fb..7caca5f64fd 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -77,6 +77,7 @@ test: brin_bloom brin_multi # Another group of parallel tests # ---------- test: create_table_like alter_generic alter_operator misc async dbsize merge misc_functions nls sysviews tsrf tid tidscan tidrangescan collate.utf8 collate.icu.utf8 incremental_sort create_role without_overlaps generated_virtual +test: incremental_matview # collate.linux.utf8 and collate.icu.utf8 tests cannot be run in parallel with each other # psql depends on create_am diff --git a/src/test/regress/sql/incremental_matview.sql b/src/test/regress/sql/incremental_matview.sql new file mode 100644 index 00000000000..2d55c393d6f --- /dev/null +++ b/src/test/regress/sql/incremental_matview.sql @@ -0,0 +1,580 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); + +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +REFRESH MATERIALIZED VIEW mv_ivm_1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; + +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; +ROLLBACK; + +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +DROP MATERIALIZED VIEW mv_ivm_rename; + +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +DROP MATERIALIZED VIEW mv_ivm_unique; + +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; + + +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +ROLLBACK; + +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +ROLLBACK; + +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +ROLLBACK; + +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +ROLLBACK; + +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +ROLLBACK; + +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min; + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); + +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; +ROLLBACK; + +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +SELECT * FROM mv_self ORDER BY v1; +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; +SELECT * FROM mv_self ORDER BY v1; + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + +ROLLBACK; + +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +SELECT * FROM mv ORDER BY v1; +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; +SELECT * FROM mv ORDER BY v1; +ROLLBACK; + +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +SELECT * FROM mv_ri ORDER BY i1; +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; +ROLLBACK; + +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +-- IMMV containing user defined type +BEGIN; + +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); + +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; + +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); + +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); + +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + +ROLLBACK; + +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; + +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; + +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; + +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; + +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; + +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); + +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; + +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); + +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ROLLBACK; + +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; + +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; + +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; + +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; + +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; + +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; + +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); + +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +DROP USER IF EXISTS regress_ivm_user; +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; + +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); + +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; + +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; + +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; +RESET SESSION AUTHORIZATION; + +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +RESET SESSION AUTHORIZATION; + +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; +ROLLBACK; + +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); + +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; + +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; + +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; + +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; + +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); + +ROLLBACK; + +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ROLLBACK; + +-- cleanup + +DROP TABLE rls_tbl CASCADE; +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; + +DROP TABLE mv_base_b CASCADE; +DROP TABLE mv_base_a CASCADE; -- 2.43.0 --Multipart=_Fri__29_May_2026_23_14_17_+0900_Te0o73X2VqYK57Gd Content-Type: text/x-diff; name="v37-0009-Add-support-for-min-max-aggregates-for-IVM.patch" Content-Disposition: attachment; filename="v37-0009-Add-support-for-min-max-aggregates-for-IVM.patch" Content-Transfer-Encoding: 7bit ^ permalink raw reply [nested|flat] 78+ messages in thread
* [PATCH v37 10/11] Add regression tests for Incremental View Maintenance @ 2026-05-29 09:31 Yugo Nagata <[email protected]> 0 siblings, 0 replies; 78+ messages in thread From: Yugo Nagata @ 2026-05-29 09:31 UTC (permalink / raw) --- src/test/isolation/isolation_schedule | 9 + .../regress/expected/incremental_matview.out | 1100 +++++++++++++++++ src/test/regress/parallel_schedule | 1 + src/test/regress/sql/incremental_matview.sql | 580 +++++++++ 4 files changed, 1690 insertions(+) create mode 100644 src/test/regress/expected/incremental_matview.out create mode 100644 src/test/regress/sql/incremental_matview.sql diff --git a/src/test/isolation/isolation_schedule b/src/test/isolation/isolation_schedule index 15c33fad4c5..111fd465207 100644 --- a/src/test/isolation/isolation_schedule +++ b/src/test/isolation/isolation_schedule @@ -127,3 +127,12 @@ test: matview-write-skew test: lock-nowait test: for-portion-of test: ddl-dependency-locking +test: ivm-create-insert +test: ivm-create-insert2 +test: ivm-create-insert3 +test: ivm-insert-insert +test: ivm-insert-insert2 +test: ivm-insert-insert3 +test: ivm-refresh-insert +test: ivm-refresh-insert2 +test: ivm-refresh-insert3 diff --git a/src/test/regress/expected/incremental_matview.out b/src/test/regress/expected/incremental_matview.out new file mode 100644 index 00000000000..f215aa88e48 --- /dev/null +++ b/src/test/regress/expected/incremental_matview.out @@ -0,0 +1,1100 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ERROR: materialized view "mv_ivm_1" has not been populated +HINT: Use the REFRESH MATERIALIZED VIEW command. +REFRESH MATERIALIZED VIEW mv_ivm_1; +NOTICE: could not create an index on materialized view "mv_ivm_1" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 17 +(1 row) + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 1 +(1 row) + +ROLLBACK; +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_rename_index" on materialized view "mv_ivm_rename" +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +ERROR: IVM column can not be renamed +DROP MATERIALIZED VIEW mv_ivm_rename; +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_unique_index" on materialized view "mv_ivm_unique" +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +ERROR: unique index creation on IVM columns is not supported +DROP MATERIALIZED VIEW mv_ivm_unique; +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +NOTICE: could not create an index on materialized view "mv_ivm_func" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +NOTICE: could not create an index on materialized view "mv_ivm_no_tbl" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_duplicate" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +NOTICE: created index "mv_ivm_distinct_index" on materialized view "mv_ivm_distinct" +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 20 + 30 + 40 + 50 +(6 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +ROLLBACK; +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 120 | 2 | 60.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+---------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 220 | 2 | 110.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 20 | 1 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 120 | 2 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; + sum | count +-----+------- +(0 rows) + +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; + i | sum | count +---+-----+------- +(0 rows) + +ROLLBACK; +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 150 | 5 | 30.0000000000000000 +(1 row) + +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 210 | 6 | 35.0000000000000000 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +NOTICE: created index "mv_ivm_avg_bug_index" on materialized view "mv_ivm_avg_bug" +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 3 | 3.3333333333333333 + 2 | 80 | 3 | 26.6666666666666667 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_min_max_index" on materialized view "mv_ivm_min_max" +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 10 + 2 | 20 | 20 + 3 | 30 | 30 + 4 | 40 | 40 + 5 | 50 | 50 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 12 + 2 | 20 | 22 + 3 | 30 | 32 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 11 | 12 + 2 | 20 | 22 + 3 | 30 | 31 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min_max" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 50 +(1 row) + +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 0 | 70 +(1 row) + +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 60 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + | +(1 row) + +ROLLBACK; +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min; + min +----- + 10 +(1 row) + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + min +----- + 20 +(1 row) + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; + min +----- + 30 +(1 row) + +ROLLBACK; +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | sum +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | b +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ERROR: too many column names were specified +ROLLBACK; +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +NOTICE: could not create an index on materialized view "mv_self" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +----+---- + 10 | 10 + 20 | 20 + 30 | 30 +(3 rows) + +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 30 | 30 + 40 | 40 + 200 | 200 +(3 rows) + +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 130 | 130 + 300 | 300 +(4 rows) + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 70 | 70 + 70 | 77 + 77 | 70 + 77 | 77 + 130 | 130 + 300 | 300 +(8 rows) + +ROLLBACK; +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY v1; + v1 | v2 +----+----- + 10 | 100 + 20 | 200 + 30 | 300 +(3 rows) + +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv ORDER BY v1; + v1 | v2 +------+----- + 10 | 100 + 11 | 100 + 1020 | 200 + 1020 | 222 +(4 rows) + +ROLLBACK; +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +NOTICE: created index "mv_ri_index" on materialized view "mv_ri" +SELECT * FROM mv_ri ORDER BY i1; + i1 | i2 +----+---- + 1 | 1 + 2 | 2 + 3 | 3 +(3 rows) + +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; + i1 | i2 +----+---- + 3 | 3 + 10 | 10 +(2 rows) + +ROLLBACK; +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | +(2 rows) + +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | 20 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i +--- +(0 rows) + +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; + i +--- + 1 + +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 30 + | 3 +(2 rows) + +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 300 + | 30 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 1 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 4 +(1 row) + +ROLLBACK; +-- IMMV containing user defined type +BEGIN; +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: return type mytype is only a shell +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: argument type mytype is only a shell +LINE 1: CREATE FUNCTION mytype_out(mytype) + ^ +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +NOTICE: could not create an index on materialized view "mv_mytype" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + x +--- + 1 +(1 row) + +ROLLBACK; +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +ERROR: OUTER JOIN is not supported on incrementally maintainable materialized view +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +ERROR: CTE is not supported on incrementally maintainable materialized view +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +ERROR: ORDER BY clause is not supported on incrementally maintainable materialized view +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; +ERROR: HAVING clause is not supported on incrementally maintainable materialized view +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; +ERROR: mutable function is not supported on incrementally maintainable materialized view +HINT: functions must be marked IMMUTABLE +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; +ERROR: LIMIT/OFFSET clause is not supported on incrementally maintainable materialized view +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; +ERROR: DISTINCT ON is not supported on incrementally maintainable materialized view +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); +ERROR: TABLESAMPLE clause is not supported on incrementally maintainable materialized view +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; +ERROR: window functions are not supported on incrementally maintainable materialized view +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +ERROR: aggregate function with FILTER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +ERROR: aggregate function with DISTINCT arguments is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +ERROR: aggregate function with ORDER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); +ERROR: GROUPING SETS, ROLLUP, or CUBE clauses is not supported on incrementally maintainable materialized view +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ERROR: inheritance parent is not supported on incrementally maintainable materialized view +ROLLBACK; +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; +ERROR: UNION/INTERSECT/EXCEPT statements are not supported on incrementally maintainable materialized view +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; +ERROR: empty target list is not supported on incrementally maintainable materialized view +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; +ERROR: FOR UPDATE/SHARE clause is not supported on incrementally maintainable materialized view +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; +ERROR: column name __ivm_count__ is not supported on incrementally maintainable materialized view +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; +ERROR: GROUP BY expression not appearing in select list is not supported on incrementally maintainable materialized view +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); +ERROR: VALUES is not supported on incrementally maintainable materialized view +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +NOTICE: role "regress_ivm_admin" does not exist, skipping +DROP USER IF EXISTS regress_ivm_user; +NOTICE: role "regress_ivm_user" does not exist, skipping +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +NOTICE: could not create an index on materialized view "ivm_rls" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user +(1 row) + +RESET SESSION AUTHORIZATION; +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user + 3 | baz | regress_ivm_user +(2 rows) + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +-- +(1 row) + +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+-------+------------------ + 2 | bar | regress_ivm_user + 3 | baz | regress_ivm_user + 6 | corge | regress_ivm_user +(3 rows) + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +NOTICE: could not create an index on materialized view "ivm_rls2" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +RESET SESSION AUTHORIZATION; +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +-- +(1 row) + +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + id | data | owner | num +----+-------+------------------+--------- + 2 | bar | regress_ivm_user | two + 3 | baz_2 | regress_ivm_user | three_2 + 6 | corge | regress_ivm_user | six +(3 rows) + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +NOTICE: could not create an index on materialized view "mv_update_same" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + i +--- + 2 +(1 row) + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +NOTICE: created index "mv_self_ref_index" on materialized view "mv_self_ref" +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; + a | b +----+---- + 11 | + 12 | 11 + 13 | 12 +(3 rows) + +ROLLBACK; +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; +NOTICE: created index "mv_idx1_index" on materialized view "mv_idx1" +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; +NOTICE: created index "mv_idx2_index" on materialized view "mv_idx2" +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; +NOTICE: created index "mv_idx3_index" on materialized view "mv_idx3" +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +NOTICE: could not create an index on materialized view "mv_idx4" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; +NOTICE: could not create an index on materialized view "mv_idx5" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); +NOTICE: could not create an index on materialized view "mv_idx6" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ERROR: data type json has no default operator class for access method "btree" +ROLLBACK; +-- cleanup +DROP TABLE rls_tbl CASCADE; +NOTICE: drop cascades to 2 other objects +DETAIL: drop cascades to materialized view ivm_rls +drop cascades to materialized view ivm_rls2 +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; +DROP TABLE mv_base_b CASCADE; +NOTICE: drop cascades to 3 other objects +DETAIL: drop cascades to materialized view mv_ivm_1 +drop cascades to view b_view +drop cascades to materialized view b_mview +DROP TABLE mv_base_a CASCADE; diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index 8fa0a6c47fb..7caca5f64fd 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -77,6 +77,7 @@ test: brin_bloom brin_multi # Another group of parallel tests # ---------- test: create_table_like alter_generic alter_operator misc async dbsize merge misc_functions nls sysviews tsrf tid tidscan tidrangescan collate.utf8 collate.icu.utf8 incremental_sort create_role without_overlaps generated_virtual +test: incremental_matview # collate.linux.utf8 and collate.icu.utf8 tests cannot be run in parallel with each other # psql depends on create_am diff --git a/src/test/regress/sql/incremental_matview.sql b/src/test/regress/sql/incremental_matview.sql new file mode 100644 index 00000000000..2d55c393d6f --- /dev/null +++ b/src/test/regress/sql/incremental_matview.sql @@ -0,0 +1,580 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); + +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +REFRESH MATERIALIZED VIEW mv_ivm_1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; + +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; +ROLLBACK; + +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +DROP MATERIALIZED VIEW mv_ivm_rename; + +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +DROP MATERIALIZED VIEW mv_ivm_unique; + +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; + + +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +ROLLBACK; + +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +ROLLBACK; + +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +ROLLBACK; + +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +ROLLBACK; + +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +ROLLBACK; + +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min; + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); + +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; +ROLLBACK; + +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +SELECT * FROM mv_self ORDER BY v1; +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; +SELECT * FROM mv_self ORDER BY v1; + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + +ROLLBACK; + +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +SELECT * FROM mv ORDER BY v1; +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; +SELECT * FROM mv ORDER BY v1; +ROLLBACK; + +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +SELECT * FROM mv_ri ORDER BY i1; +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; +ROLLBACK; + +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +-- IMMV containing user defined type +BEGIN; + +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); + +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; + +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); + +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); + +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + +ROLLBACK; + +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; + +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; + +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; + +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; + +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; + +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); + +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; + +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); + +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ROLLBACK; + +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; + +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; + +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; + +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; + +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; + +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; + +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); + +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +DROP USER IF EXISTS regress_ivm_user; +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; + +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); + +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; + +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; + +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; +RESET SESSION AUTHORIZATION; + +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +RESET SESSION AUTHORIZATION; + +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; +ROLLBACK; + +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); + +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; + +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; + +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; + +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; + +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); + +ROLLBACK; + +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ROLLBACK; + +-- cleanup + +DROP TABLE rls_tbl CASCADE; +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; + +DROP TABLE mv_base_b CASCADE; +DROP TABLE mv_base_a CASCADE; -- 2.43.0 --Multipart=_Fri__29_May_2026_23_14_17_+0900_Te0o73X2VqYK57Gd Content-Type: text/x-diff; name="v37-0009-Add-support-for-min-max-aggregates-for-IVM.patch" Content-Disposition: attachment; filename="v37-0009-Add-support-for-min-max-aggregates-for-IVM.patch" Content-Transfer-Encoding: 7bit ^ permalink raw reply [nested|flat] 78+ messages in thread
* [PATCH v37 10/11] Add regression tests for Incremental View Maintenance @ 2026-05-29 09:31 Yugo Nagata <[email protected]> 0 siblings, 0 replies; 78+ messages in thread From: Yugo Nagata @ 2026-05-29 09:31 UTC (permalink / raw) --- src/test/isolation/isolation_schedule | 9 + .../regress/expected/incremental_matview.out | 1100 +++++++++++++++++ src/test/regress/parallel_schedule | 1 + src/test/regress/sql/incremental_matview.sql | 580 +++++++++ 4 files changed, 1690 insertions(+) create mode 100644 src/test/regress/expected/incremental_matview.out create mode 100644 src/test/regress/sql/incremental_matview.sql diff --git a/src/test/isolation/isolation_schedule b/src/test/isolation/isolation_schedule index 15c33fad4c5..111fd465207 100644 --- a/src/test/isolation/isolation_schedule +++ b/src/test/isolation/isolation_schedule @@ -127,3 +127,12 @@ test: matview-write-skew test: lock-nowait test: for-portion-of test: ddl-dependency-locking +test: ivm-create-insert +test: ivm-create-insert2 +test: ivm-create-insert3 +test: ivm-insert-insert +test: ivm-insert-insert2 +test: ivm-insert-insert3 +test: ivm-refresh-insert +test: ivm-refresh-insert2 +test: ivm-refresh-insert3 diff --git a/src/test/regress/expected/incremental_matview.out b/src/test/regress/expected/incremental_matview.out new file mode 100644 index 00000000000..f215aa88e48 --- /dev/null +++ b/src/test/regress/expected/incremental_matview.out @@ -0,0 +1,1100 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ERROR: materialized view "mv_ivm_1" has not been populated +HINT: Use the REFRESH MATERIALIZED VIEW command. +REFRESH MATERIALIZED VIEW mv_ivm_1; +NOTICE: could not create an index on materialized view "mv_ivm_1" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 17 +(1 row) + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 1 +(1 row) + +ROLLBACK; +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_rename_index" on materialized view "mv_ivm_rename" +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +ERROR: IVM column can not be renamed +DROP MATERIALIZED VIEW mv_ivm_rename; +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_unique_index" on materialized view "mv_ivm_unique" +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +ERROR: unique index creation on IVM columns is not supported +DROP MATERIALIZED VIEW mv_ivm_unique; +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +NOTICE: could not create an index on materialized view "mv_ivm_func" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +NOTICE: could not create an index on materialized view "mv_ivm_no_tbl" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_duplicate" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +NOTICE: created index "mv_ivm_distinct_index" on materialized view "mv_ivm_distinct" +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 20 + 30 + 40 + 50 +(6 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +ROLLBACK; +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 120 | 2 | 60.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+---------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 220 | 2 | 110.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 20 | 1 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 120 | 2 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; + sum | count +-----+------- +(0 rows) + +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; + i | sum | count +---+-----+------- +(0 rows) + +ROLLBACK; +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 150 | 5 | 30.0000000000000000 +(1 row) + +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 210 | 6 | 35.0000000000000000 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +NOTICE: created index "mv_ivm_avg_bug_index" on materialized view "mv_ivm_avg_bug" +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 3 | 3.3333333333333333 + 2 | 80 | 3 | 26.6666666666666667 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_min_max_index" on materialized view "mv_ivm_min_max" +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 10 + 2 | 20 | 20 + 3 | 30 | 30 + 4 | 40 | 40 + 5 | 50 | 50 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 12 + 2 | 20 | 22 + 3 | 30 | 32 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 11 | 12 + 2 | 20 | 22 + 3 | 30 | 31 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min_max" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 50 +(1 row) + +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 0 | 70 +(1 row) + +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 60 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + | +(1 row) + +ROLLBACK; +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min; + min +----- + 10 +(1 row) + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + min +----- + 20 +(1 row) + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; + min +----- + 30 +(1 row) + +ROLLBACK; +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | sum +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | b +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ERROR: too many column names were specified +ROLLBACK; +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +NOTICE: could not create an index on materialized view "mv_self" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +----+---- + 10 | 10 + 20 | 20 + 30 | 30 +(3 rows) + +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 30 | 30 + 40 | 40 + 200 | 200 +(3 rows) + +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 130 | 130 + 300 | 300 +(4 rows) + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 70 | 70 + 70 | 77 + 77 | 70 + 77 | 77 + 130 | 130 + 300 | 300 +(8 rows) + +ROLLBACK; +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY v1; + v1 | v2 +----+----- + 10 | 100 + 20 | 200 + 30 | 300 +(3 rows) + +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv ORDER BY v1; + v1 | v2 +------+----- + 10 | 100 + 11 | 100 + 1020 | 200 + 1020 | 222 +(4 rows) + +ROLLBACK; +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +NOTICE: created index "mv_ri_index" on materialized view "mv_ri" +SELECT * FROM mv_ri ORDER BY i1; + i1 | i2 +----+---- + 1 | 1 + 2 | 2 + 3 | 3 +(3 rows) + +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; + i1 | i2 +----+---- + 3 | 3 + 10 | 10 +(2 rows) + +ROLLBACK; +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | +(2 rows) + +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | 20 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i +--- +(0 rows) + +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; + i +--- + 1 + +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 30 + | 3 +(2 rows) + +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 300 + | 30 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 1 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 4 +(1 row) + +ROLLBACK; +-- IMMV containing user defined type +BEGIN; +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: return type mytype is only a shell +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: argument type mytype is only a shell +LINE 1: CREATE FUNCTION mytype_out(mytype) + ^ +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +NOTICE: could not create an index on materialized view "mv_mytype" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + x +--- + 1 +(1 row) + +ROLLBACK; +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +ERROR: OUTER JOIN is not supported on incrementally maintainable materialized view +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +ERROR: CTE is not supported on incrementally maintainable materialized view +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +ERROR: ORDER BY clause is not supported on incrementally maintainable materialized view +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; +ERROR: HAVING clause is not supported on incrementally maintainable materialized view +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; +ERROR: mutable function is not supported on incrementally maintainable materialized view +HINT: functions must be marked IMMUTABLE +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; +ERROR: LIMIT/OFFSET clause is not supported on incrementally maintainable materialized view +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; +ERROR: DISTINCT ON is not supported on incrementally maintainable materialized view +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); +ERROR: TABLESAMPLE clause is not supported on incrementally maintainable materialized view +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; +ERROR: window functions are not supported on incrementally maintainable materialized view +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +ERROR: aggregate function with FILTER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +ERROR: aggregate function with DISTINCT arguments is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +ERROR: aggregate function with ORDER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); +ERROR: GROUPING SETS, ROLLUP, or CUBE clauses is not supported on incrementally maintainable materialized view +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ERROR: inheritance parent is not supported on incrementally maintainable materialized view +ROLLBACK; +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; +ERROR: UNION/INTERSECT/EXCEPT statements are not supported on incrementally maintainable materialized view +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; +ERROR: empty target list is not supported on incrementally maintainable materialized view +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; +ERROR: FOR UPDATE/SHARE clause is not supported on incrementally maintainable materialized view +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; +ERROR: column name __ivm_count__ is not supported on incrementally maintainable materialized view +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; +ERROR: GROUP BY expression not appearing in select list is not supported on incrementally maintainable materialized view +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); +ERROR: VALUES is not supported on incrementally maintainable materialized view +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +NOTICE: role "regress_ivm_admin" does not exist, skipping +DROP USER IF EXISTS regress_ivm_user; +NOTICE: role "regress_ivm_user" does not exist, skipping +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +NOTICE: could not create an index on materialized view "ivm_rls" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user +(1 row) + +RESET SESSION AUTHORIZATION; +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user + 3 | baz | regress_ivm_user +(2 rows) + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +-- +(1 row) + +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+-------+------------------ + 2 | bar | regress_ivm_user + 3 | baz | regress_ivm_user + 6 | corge | regress_ivm_user +(3 rows) + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +NOTICE: could not create an index on materialized view "ivm_rls2" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +RESET SESSION AUTHORIZATION; +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +-- +(1 row) + +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + id | data | owner | num +----+-------+------------------+--------- + 2 | bar | regress_ivm_user | two + 3 | baz_2 | regress_ivm_user | three_2 + 6 | corge | regress_ivm_user | six +(3 rows) + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +NOTICE: could not create an index on materialized view "mv_update_same" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + i +--- + 2 +(1 row) + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +NOTICE: created index "mv_self_ref_index" on materialized view "mv_self_ref" +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; + a | b +----+---- + 11 | + 12 | 11 + 13 | 12 +(3 rows) + +ROLLBACK; +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; +NOTICE: created index "mv_idx1_index" on materialized view "mv_idx1" +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; +NOTICE: created index "mv_idx2_index" on materialized view "mv_idx2" +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; +NOTICE: created index "mv_idx3_index" on materialized view "mv_idx3" +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +NOTICE: could not create an index on materialized view "mv_idx4" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; +NOTICE: could not create an index on materialized view "mv_idx5" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); +NOTICE: could not create an index on materialized view "mv_idx6" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ERROR: data type json has no default operator class for access method "btree" +ROLLBACK; +-- cleanup +DROP TABLE rls_tbl CASCADE; +NOTICE: drop cascades to 2 other objects +DETAIL: drop cascades to materialized view ivm_rls +drop cascades to materialized view ivm_rls2 +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; +DROP TABLE mv_base_b CASCADE; +NOTICE: drop cascades to 3 other objects +DETAIL: drop cascades to materialized view mv_ivm_1 +drop cascades to view b_view +drop cascades to materialized view b_mview +DROP TABLE mv_base_a CASCADE; diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index 8fa0a6c47fb..7caca5f64fd 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -77,6 +77,7 @@ test: brin_bloom brin_multi # Another group of parallel tests # ---------- test: create_table_like alter_generic alter_operator misc async dbsize merge misc_functions nls sysviews tsrf tid tidscan tidrangescan collate.utf8 collate.icu.utf8 incremental_sort create_role without_overlaps generated_virtual +test: incremental_matview # collate.linux.utf8 and collate.icu.utf8 tests cannot be run in parallel with each other # psql depends on create_am diff --git a/src/test/regress/sql/incremental_matview.sql b/src/test/regress/sql/incremental_matview.sql new file mode 100644 index 00000000000..2d55c393d6f --- /dev/null +++ b/src/test/regress/sql/incremental_matview.sql @@ -0,0 +1,580 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); + +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +REFRESH MATERIALIZED VIEW mv_ivm_1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; + +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; +ROLLBACK; + +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +DROP MATERIALIZED VIEW mv_ivm_rename; + +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +DROP MATERIALIZED VIEW mv_ivm_unique; + +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; + + +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +ROLLBACK; + +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +ROLLBACK; + +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +ROLLBACK; + +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +ROLLBACK; + +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +ROLLBACK; + +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min; + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); + +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; +ROLLBACK; + +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +SELECT * FROM mv_self ORDER BY v1; +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; +SELECT * FROM mv_self ORDER BY v1; + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + +ROLLBACK; + +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +SELECT * FROM mv ORDER BY v1; +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; +SELECT * FROM mv ORDER BY v1; +ROLLBACK; + +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +SELECT * FROM mv_ri ORDER BY i1; +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; +ROLLBACK; + +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +-- IMMV containing user defined type +BEGIN; + +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); + +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; + +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); + +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); + +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + +ROLLBACK; + +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; + +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; + +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; + +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; + +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; + +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); + +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; + +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); + +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ROLLBACK; + +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; + +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; + +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; + +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; + +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; + +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; + +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); + +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +DROP USER IF EXISTS regress_ivm_user; +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; + +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); + +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; + +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; + +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; +RESET SESSION AUTHORIZATION; + +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +RESET SESSION AUTHORIZATION; + +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; +ROLLBACK; + +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); + +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; + +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; + +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; + +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; + +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); + +ROLLBACK; + +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ROLLBACK; + +-- cleanup + +DROP TABLE rls_tbl CASCADE; +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; + +DROP TABLE mv_base_b CASCADE; +DROP TABLE mv_base_a CASCADE; -- 2.43.0 --Multipart=_Fri__29_May_2026_23_14_17_+0900_Te0o73X2VqYK57Gd Content-Type: text/x-diff; name="v37-0009-Add-support-for-min-max-aggregates-for-IVM.patch" Content-Disposition: attachment; filename="v37-0009-Add-support-for-min-max-aggregates-for-IVM.patch" Content-Transfer-Encoding: 7bit ^ permalink raw reply [nested|flat] 78+ messages in thread
* [PATCH v38 10/11] Add regression tests for Incremental View Maintenance @ 2026-05-29 09:31 Yugo Nagata <[email protected]> 0 siblings, 0 replies; 78+ messages in thread From: Yugo Nagata @ 2026-05-29 09:31 UTC (permalink / raw) --- .../isolation/expected/ivm-create-insert.out | 285 +++++ .../isolation/expected/ivm-create-insert2.out | 305 +++++ .../isolation/expected/ivm-create-insert3.out | 305 +++++ .../isolation/expected/ivm-insert-insert.out | 497 ++++++++ .../isolation/expected/ivm-insert-insert2.out | 373 ++++++ .../isolation/expected/ivm-insert-insert3.out | 373 ++++++ .../isolation/expected/ivm-refresh-insert.out | 213 ++++ .../expected/ivm-refresh-insert2.out | 191 +++ .../expected/ivm-refresh-insert3.out | 191 +++ src/test/isolation/isolation_schedule | 9 + .../isolation/specs/ivm-create-insert.spec | 47 + .../isolation/specs/ivm-create-insert2.spec | 54 + .../isolation/specs/ivm-create-insert3.spec | 54 + .../isolation/specs/ivm-insert-insert.spec | 62 + .../isolation/specs/ivm-insert-insert2.spec | 62 + .../isolation/specs/ivm-insert-insert3.spec | 62 + .../isolation/specs/ivm-refresh-insert.spec | 46 + .../isolation/specs/ivm-refresh-insert2.spec | 46 + .../isolation/specs/ivm-refresh-insert3.spec | 46 + .../regress/expected/incremental_matview.out | 1100 +++++++++++++++++ src/test/regress/parallel_schedule | 1 + src/test/regress/sql/incremental_matview.sql | 580 +++++++++ 22 files changed, 4902 insertions(+) create mode 100644 src/test/isolation/expected/ivm-create-insert.out create mode 100644 src/test/isolation/expected/ivm-create-insert2.out create mode 100644 src/test/isolation/expected/ivm-create-insert3.out create mode 100644 src/test/isolation/expected/ivm-insert-insert.out create mode 100644 src/test/isolation/expected/ivm-insert-insert2.out create mode 100644 src/test/isolation/expected/ivm-insert-insert3.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert2.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert3.out create mode 100644 src/test/isolation/specs/ivm-create-insert.spec create mode 100644 src/test/isolation/specs/ivm-create-insert2.spec create mode 100644 src/test/isolation/specs/ivm-create-insert3.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert2.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert3.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert2.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert3.spec create mode 100644 src/test/regress/expected/incremental_matview.out create mode 100644 src/test/regress/sql/incremental_matview.sql diff --git a/src/test/isolation/expected/ivm-create-insert.out b/src/test/isolation/expected/ivm-create-insert.out new file mode 100644 index 00000000000..5da00043aba --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert.out @@ -0,0 +1,285 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-create-insert2.out b/src/test/isolation/expected/ivm-create-insert2.out new file mode 100644 index 00000000000..907d892c6d4 --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert2.out @@ -0,0 +1,305 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + diff --git a/src/test/isolation/expected/ivm-create-insert3.out b/src/test/isolation/expected/ivm-create-insert3.out new file mode 100644 index 00000000000..907d892c6d4 --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert3.out @@ -0,0 +1,305 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert.out b/src/test/isolation/expected/ivm-insert-insert.out new file mode 100644 index 00000000000..5ca4cfea677 --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert.out @@ -0,0 +1,497 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; <waiting ...> +step c1: COMMIT; +step update2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; <waiting ...> +step c1: COMMIT; +step update2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; <waiting ...> +step c2: COMMIT; +step update1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; <waiting ...> +step c2: COMMIT; +step update1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); <waiting ...> +step c1: COMMIT; +step insert2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); <waiting ...> +step c1: COMMIT; +step insert2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); <waiting ...> +step c2: COMMIT; +step insert1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); <waiting ...> +step c2: COMMIT; +step insert1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert2.out b/src/test/isolation/expected/ivm-insert-insert2.out new file mode 100644 index 00000000000..e1c66d4de5e --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert2.out @@ -0,0 +1,373 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert3.out b/src/test/isolation/expected/ivm-insert-insert3.out new file mode 100644 index 00000000000..e1c66d4de5e --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert3.out @@ -0,0 +1,373 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert.out b/src/test/isolation/expected/ivm-refresh-insert.out new file mode 100644 index 00000000000..a925938bf1c --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert.out @@ -0,0 +1,213 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert2.out b/src/test/isolation/expected/ivm-refresh-insert2.out new file mode 100644 index 00000000000..dc1b16ae34e --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert2.out @@ -0,0 +1,191 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert3.out b/src/test/isolation/expected/ivm-refresh-insert3.out new file mode 100644 index 00000000000..dc1b16ae34e --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert3.out @@ -0,0 +1,191 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/isolation_schedule b/src/test/isolation/isolation_schedule index b8ebe92553c..6b7e873b370 100644 --- a/src/test/isolation/isolation_schedule +++ b/src/test/isolation/isolation_schedule @@ -128,3 +128,12 @@ test: matview-write-skew test: lock-nowait test: for-portion-of test: ddl-dependency-locking +test: ivm-create-insert +test: ivm-create-insert2 +test: ivm-create-insert3 +test: ivm-insert-insert +test: ivm-insert-insert2 +test: ivm-insert-insert3 +test: ivm-refresh-insert +test: ivm-refresh-insert2 +test: ivm-refresh-insert3 diff --git a/src/test/isolation/specs/ivm-create-insert.spec b/src/test/isolation/specs/ivm-create-insert.spec new file mode 100644 index 00000000000..ccd6fd080a9 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert.spec @@ -0,0 +1,47 @@ +# Test interaction between concurrent transactions performing +# create and insert in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-create-insert2.spec b/src/test/isolation/specs/ivm-create-insert2.spec new file mode 100644 index 00000000000..02cec85ae07 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert2.spec @@ -0,0 +1,54 @@ +# Test interaction between concurrent transactions performing +# create and insert in REPEATABLE READ isolation level +# +# Note: +# In this isolation level, it is possible that create_immv could +# create an inconsistent view not including effects of a concurrent +# transaction. So, an warning message is raised to suggest using it +# in READ COMMITTED or executing refresh_immv to make sure to +# make the view contents consistent. + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-create-insert3.spec b/src/test/isolation/specs/ivm-create-insert3.spec new file mode 100644 index 00000000000..19ce03185a4 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert3.spec @@ -0,0 +1,54 @@ +# Test interaction between concurrent transactions performing +# create and insert in SERIALIZABLE isolation level +# +# Note: +# In this isolation level, it is possible that create_immv could +# create an inconsistent view not including effects of a concurrent +# transaction. So, an warning message is raised to suggest using it +# in READ COMMITTED or executing refresh_immv to make sure to +# make the view contents consistent. + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert.spec b/src/test/isolation/specs/ivm-insert-insert.spec new file mode 100644 index 00000000000..b8f794ca191 --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert2.spec b/src/test/isolation/specs/ivm-insert-insert2.spec new file mode 100644 index 00000000000..ed086d1ba1e --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert2.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in REPEATABLE READ isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert3.spec b/src/test/isolation/specs/ivm-insert-insert3.spec new file mode 100644 index 00000000000..b18bd121033 --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert3.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in SERIALIZABLE isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert.spec b/src/test/isolation/specs/ivm-refresh-insert.spec new file mode 100644 index 00000000000..d7181251962 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert2.spec b/src/test/isolation/specs/ivm-refresh-insert2.spec new file mode 100644 index 00000000000..f2d1d5013f2 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert2.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in REPEATABLE READ isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert3.spec b/src/test/isolation/specs/ivm-refresh-insert3.spec new file mode 100644 index 00000000000..0ec2b1d1de0 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert3.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in SERIALIZABLE isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/regress/expected/incremental_matview.out b/src/test/regress/expected/incremental_matview.out new file mode 100644 index 00000000000..f215aa88e48 --- /dev/null +++ b/src/test/regress/expected/incremental_matview.out @@ -0,0 +1,1100 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ERROR: materialized view "mv_ivm_1" has not been populated +HINT: Use the REFRESH MATERIALIZED VIEW command. +REFRESH MATERIALIZED VIEW mv_ivm_1; +NOTICE: could not create an index on materialized view "mv_ivm_1" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 17 +(1 row) + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 1 +(1 row) + +ROLLBACK; +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_rename_index" on materialized view "mv_ivm_rename" +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +ERROR: IVM column can not be renamed +DROP MATERIALIZED VIEW mv_ivm_rename; +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_unique_index" on materialized view "mv_ivm_unique" +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +ERROR: unique index creation on IVM columns is not supported +DROP MATERIALIZED VIEW mv_ivm_unique; +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +NOTICE: could not create an index on materialized view "mv_ivm_func" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +NOTICE: could not create an index on materialized view "mv_ivm_no_tbl" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_duplicate" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +NOTICE: created index "mv_ivm_distinct_index" on materialized view "mv_ivm_distinct" +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 20 + 30 + 40 + 50 +(6 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +ROLLBACK; +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 120 | 2 | 60.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+---------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 220 | 2 | 110.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 20 | 1 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 120 | 2 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; + sum | count +-----+------- +(0 rows) + +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; + i | sum | count +---+-----+------- +(0 rows) + +ROLLBACK; +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 150 | 5 | 30.0000000000000000 +(1 row) + +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 210 | 6 | 35.0000000000000000 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +NOTICE: created index "mv_ivm_avg_bug_index" on materialized view "mv_ivm_avg_bug" +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 3 | 3.3333333333333333 + 2 | 80 | 3 | 26.6666666666666667 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_min_max_index" on materialized view "mv_ivm_min_max" +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 10 + 2 | 20 | 20 + 3 | 30 | 30 + 4 | 40 | 40 + 5 | 50 | 50 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 12 + 2 | 20 | 22 + 3 | 30 | 32 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 11 | 12 + 2 | 20 | 22 + 3 | 30 | 31 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min_max" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 50 +(1 row) + +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 0 | 70 +(1 row) + +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 60 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + | +(1 row) + +ROLLBACK; +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min; + min +----- + 10 +(1 row) + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + min +----- + 20 +(1 row) + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; + min +----- + 30 +(1 row) + +ROLLBACK; +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | sum +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | b +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ERROR: too many column names were specified +ROLLBACK; +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +NOTICE: could not create an index on materialized view "mv_self" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +----+---- + 10 | 10 + 20 | 20 + 30 | 30 +(3 rows) + +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 30 | 30 + 40 | 40 + 200 | 200 +(3 rows) + +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 130 | 130 + 300 | 300 +(4 rows) + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 70 | 70 + 70 | 77 + 77 | 70 + 77 | 77 + 130 | 130 + 300 | 300 +(8 rows) + +ROLLBACK; +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY v1; + v1 | v2 +----+----- + 10 | 100 + 20 | 200 + 30 | 300 +(3 rows) + +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv ORDER BY v1; + v1 | v2 +------+----- + 10 | 100 + 11 | 100 + 1020 | 200 + 1020 | 222 +(4 rows) + +ROLLBACK; +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +NOTICE: created index "mv_ri_index" on materialized view "mv_ri" +SELECT * FROM mv_ri ORDER BY i1; + i1 | i2 +----+---- + 1 | 1 + 2 | 2 + 3 | 3 +(3 rows) + +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; + i1 | i2 +----+---- + 3 | 3 + 10 | 10 +(2 rows) + +ROLLBACK; +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | +(2 rows) + +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | 20 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i +--- +(0 rows) + +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; + i +--- + 1 + +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 30 + | 3 +(2 rows) + +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 300 + | 30 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 1 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 4 +(1 row) + +ROLLBACK; +-- IMMV containing user defined type +BEGIN; +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: return type mytype is only a shell +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: argument type mytype is only a shell +LINE 1: CREATE FUNCTION mytype_out(mytype) + ^ +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +NOTICE: could not create an index on materialized view "mv_mytype" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + x +--- + 1 +(1 row) + +ROLLBACK; +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +ERROR: OUTER JOIN is not supported on incrementally maintainable materialized view +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +ERROR: CTE is not supported on incrementally maintainable materialized view +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +ERROR: ORDER BY clause is not supported on incrementally maintainable materialized view +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; +ERROR: HAVING clause is not supported on incrementally maintainable materialized view +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; +ERROR: mutable function is not supported on incrementally maintainable materialized view +HINT: functions must be marked IMMUTABLE +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; +ERROR: LIMIT/OFFSET clause is not supported on incrementally maintainable materialized view +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; +ERROR: DISTINCT ON is not supported on incrementally maintainable materialized view +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); +ERROR: TABLESAMPLE clause is not supported on incrementally maintainable materialized view +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; +ERROR: window functions are not supported on incrementally maintainable materialized view +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +ERROR: aggregate function with FILTER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +ERROR: aggregate function with DISTINCT arguments is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +ERROR: aggregate function with ORDER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); +ERROR: GROUPING SETS, ROLLUP, or CUBE clauses is not supported on incrementally maintainable materialized view +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ERROR: inheritance parent is not supported on incrementally maintainable materialized view +ROLLBACK; +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; +ERROR: UNION/INTERSECT/EXCEPT statements are not supported on incrementally maintainable materialized view +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; +ERROR: empty target list is not supported on incrementally maintainable materialized view +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; +ERROR: FOR UPDATE/SHARE clause is not supported on incrementally maintainable materialized view +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; +ERROR: column name __ivm_count__ is not supported on incrementally maintainable materialized view +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; +ERROR: GROUP BY expression not appearing in select list is not supported on incrementally maintainable materialized view +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); +ERROR: VALUES is not supported on incrementally maintainable materialized view +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +NOTICE: role "regress_ivm_admin" does not exist, skipping +DROP USER IF EXISTS regress_ivm_user; +NOTICE: role "regress_ivm_user" does not exist, skipping +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +NOTICE: could not create an index on materialized view "ivm_rls" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user +(1 row) + +RESET SESSION AUTHORIZATION; +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user + 3 | baz | regress_ivm_user +(2 rows) + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +-- +(1 row) + +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+-------+------------------ + 2 | bar | regress_ivm_user + 3 | baz | regress_ivm_user + 6 | corge | regress_ivm_user +(3 rows) + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +NOTICE: could not create an index on materialized view "ivm_rls2" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +RESET SESSION AUTHORIZATION; +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +-- +(1 row) + +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + id | data | owner | num +----+-------+------------------+--------- + 2 | bar | regress_ivm_user | two + 3 | baz_2 | regress_ivm_user | three_2 + 6 | corge | regress_ivm_user | six +(3 rows) + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +NOTICE: could not create an index on materialized view "mv_update_same" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + i +--- + 2 +(1 row) + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +NOTICE: created index "mv_self_ref_index" on materialized view "mv_self_ref" +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; + a | b +----+---- + 11 | + 12 | 11 + 13 | 12 +(3 rows) + +ROLLBACK; +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; +NOTICE: created index "mv_idx1_index" on materialized view "mv_idx1" +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; +NOTICE: created index "mv_idx2_index" on materialized view "mv_idx2" +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; +NOTICE: created index "mv_idx3_index" on materialized view "mv_idx3" +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +NOTICE: could not create an index on materialized view "mv_idx4" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; +NOTICE: could not create an index on materialized view "mv_idx5" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); +NOTICE: could not create an index on materialized view "mv_idx6" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ERROR: data type json has no default operator class for access method "btree" +ROLLBACK; +-- cleanup +DROP TABLE rls_tbl CASCADE; +NOTICE: drop cascades to 2 other objects +DETAIL: drop cascades to materialized view ivm_rls +drop cascades to materialized view ivm_rls2 +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; +DROP TABLE mv_base_b CASCADE; +NOTICE: drop cascades to 3 other objects +DETAIL: drop cascades to materialized view mv_ivm_1 +drop cascades to view b_view +drop cascades to materialized view b_mview +DROP TABLE mv_base_a CASCADE; diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index 8fa0a6c47fb..7caca5f64fd 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -77,6 +77,7 @@ test: brin_bloom brin_multi # Another group of parallel tests # ---------- test: create_table_like alter_generic alter_operator misc async dbsize merge misc_functions nls sysviews tsrf tid tidscan tidrangescan collate.utf8 collate.icu.utf8 incremental_sort create_role without_overlaps generated_virtual +test: incremental_matview # collate.linux.utf8 and collate.icu.utf8 tests cannot be run in parallel with each other # psql depends on create_am diff --git a/src/test/regress/sql/incremental_matview.sql b/src/test/regress/sql/incremental_matview.sql new file mode 100644 index 00000000000..2d55c393d6f --- /dev/null +++ b/src/test/regress/sql/incremental_matview.sql @@ -0,0 +1,580 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); + +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +REFRESH MATERIALIZED VIEW mv_ivm_1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; + +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; +ROLLBACK; + +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +DROP MATERIALIZED VIEW mv_ivm_rename; + +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +DROP MATERIALIZED VIEW mv_ivm_unique; + +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; + + +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +ROLLBACK; + +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +ROLLBACK; + +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +ROLLBACK; + +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +ROLLBACK; + +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +ROLLBACK; + +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min; + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); + +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; +ROLLBACK; + +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +SELECT * FROM mv_self ORDER BY v1; +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; +SELECT * FROM mv_self ORDER BY v1; + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + +ROLLBACK; + +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +SELECT * FROM mv ORDER BY v1; +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; +SELECT * FROM mv ORDER BY v1; +ROLLBACK; + +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +SELECT * FROM mv_ri ORDER BY i1; +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; +ROLLBACK; + +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +-- IMMV containing user defined type +BEGIN; + +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); + +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; + +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); + +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); + +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + +ROLLBACK; + +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; + +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; + +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; + +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; + +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; + +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); + +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; + +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); + +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ROLLBACK; + +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; + +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; + +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; + +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; + +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; + +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; + +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); + +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +DROP USER IF EXISTS regress_ivm_user; +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; + +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); + +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; + +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; + +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; +RESET SESSION AUTHORIZATION; + +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +RESET SESSION AUTHORIZATION; + +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; +ROLLBACK; + +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); + +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; + +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; + +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; + +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; + +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); + +ROLLBACK; + +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ROLLBACK; + +-- cleanup + +DROP TABLE rls_tbl CASCADE; +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; + +DROP TABLE mv_base_b CASCADE; +DROP TABLE mv_base_a CASCADE; -- 2.43.0 --Multipart=_Wed__1_Jul_2026_00_04_01_+0900_OVSy2WWK_9aByzDJ Content-Type: text/x-diff; name="v38-0009-Add-support-for-min-max-aggregates-for-IVM.patch" Content-Disposition: attachment; filename="v38-0009-Add-support-for-min-max-aggregates-for-IVM.patch" Content-Transfer-Encoding: 7bit ^ permalink raw reply [nested|flat] 78+ messages in thread
* [PATCH v39 7/8] Add regression tests for Incremental View Maintenance @ 2026-05-29 09:31 Yugo Nagata <[email protected]> 0 siblings, 0 replies; 78+ messages in thread From: Yugo Nagata @ 2026-05-29 09:31 UTC (permalink / raw) --- .../isolation/expected/ivm-create-insert.out | 285 ++++++++ .../isolation/expected/ivm-create-insert2.out | 305 ++++++++ .../isolation/expected/ivm-create-insert3.out | 305 ++++++++ .../isolation/expected/ivm-insert-insert.out | 497 +++++++++++++ .../isolation/expected/ivm-insert-insert2.out | 373 ++++++++++ .../isolation/expected/ivm-insert-insert3.out | 373 ++++++++++ .../isolation/expected/ivm-refresh-insert.out | 213 ++++++ .../expected/ivm-refresh-insert2.out | 191 +++++ .../expected/ivm-refresh-insert3.out | 191 +++++ src/test/isolation/isolation_schedule | 9 + .../isolation/specs/ivm-create-insert.spec | 47 ++ .../isolation/specs/ivm-create-insert2.spec | 54 ++ .../isolation/specs/ivm-create-insert3.spec | 54 ++ .../isolation/specs/ivm-insert-insert.spec | 62 ++ .../isolation/specs/ivm-insert-insert2.spec | 62 ++ .../isolation/specs/ivm-insert-insert3.spec | 62 ++ .../isolation/specs/ivm-refresh-insert.spec | 46 ++ .../isolation/specs/ivm-refresh-insert2.spec | 46 ++ .../isolation/specs/ivm-refresh-insert3.spec | 46 ++ .../regress/expected/incremental_matview.out | 667 ++++++++++++++++++ src/test/regress/parallel_schedule | 1 + src/test/regress/sql/incremental_matview.sql | 407 +++++++++++ 22 files changed, 4296 insertions(+) create mode 100644 src/test/isolation/expected/ivm-create-insert.out create mode 100644 src/test/isolation/expected/ivm-create-insert2.out create mode 100644 src/test/isolation/expected/ivm-create-insert3.out create mode 100644 src/test/isolation/expected/ivm-insert-insert.out create mode 100644 src/test/isolation/expected/ivm-insert-insert2.out create mode 100644 src/test/isolation/expected/ivm-insert-insert3.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert2.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert3.out create mode 100644 src/test/isolation/specs/ivm-create-insert.spec create mode 100644 src/test/isolation/specs/ivm-create-insert2.spec create mode 100644 src/test/isolation/specs/ivm-create-insert3.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert2.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert3.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert2.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert3.spec create mode 100644 src/test/regress/expected/incremental_matview.out create mode 100644 src/test/regress/sql/incremental_matview.sql diff --git a/src/test/isolation/expected/ivm-create-insert.out b/src/test/isolation/expected/ivm-create-insert.out new file mode 100644 index 00000000000..5da00043aba --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert.out @@ -0,0 +1,285 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-create-insert2.out b/src/test/isolation/expected/ivm-create-insert2.out new file mode 100644 index 00000000000..907d892c6d4 --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert2.out @@ -0,0 +1,305 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + diff --git a/src/test/isolation/expected/ivm-create-insert3.out b/src/test/isolation/expected/ivm-create-insert3.out new file mode 100644 index 00000000000..907d892c6d4 --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert3.out @@ -0,0 +1,305 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert.out b/src/test/isolation/expected/ivm-insert-insert.out new file mode 100644 index 00000000000..5ca4cfea677 --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert.out @@ -0,0 +1,497 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; <waiting ...> +step c1: COMMIT; +step update2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; <waiting ...> +step c1: COMMIT; +step update2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; <waiting ...> +step c2: COMMIT; +step update1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; <waiting ...> +step c2: COMMIT; +step update1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); <waiting ...> +step c1: COMMIT; +step insert2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); <waiting ...> +step c1: COMMIT; +step insert2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); <waiting ...> +step c2: COMMIT; +step insert1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); <waiting ...> +step c2: COMMIT; +step insert1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert2.out b/src/test/isolation/expected/ivm-insert-insert2.out new file mode 100644 index 00000000000..e1c66d4de5e --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert2.out @@ -0,0 +1,373 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert3.out b/src/test/isolation/expected/ivm-insert-insert3.out new file mode 100644 index 00000000000..e1c66d4de5e --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert3.out @@ -0,0 +1,373 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert.out b/src/test/isolation/expected/ivm-refresh-insert.out new file mode 100644 index 00000000000..a925938bf1c --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert.out @@ -0,0 +1,213 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert2.out b/src/test/isolation/expected/ivm-refresh-insert2.out new file mode 100644 index 00000000000..dc1b16ae34e --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert2.out @@ -0,0 +1,191 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert3.out b/src/test/isolation/expected/ivm-refresh-insert3.out new file mode 100644 index 00000000000..dc1b16ae34e --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert3.out @@ -0,0 +1,191 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/isolation_schedule b/src/test/isolation/isolation_schedule index b8ebe92553c..6b7e873b370 100644 --- a/src/test/isolation/isolation_schedule +++ b/src/test/isolation/isolation_schedule @@ -128,3 +128,12 @@ test: matview-write-skew test: lock-nowait test: for-portion-of test: ddl-dependency-locking +test: ivm-create-insert +test: ivm-create-insert2 +test: ivm-create-insert3 +test: ivm-insert-insert +test: ivm-insert-insert2 +test: ivm-insert-insert3 +test: ivm-refresh-insert +test: ivm-refresh-insert2 +test: ivm-refresh-insert3 diff --git a/src/test/isolation/specs/ivm-create-insert.spec b/src/test/isolation/specs/ivm-create-insert.spec new file mode 100644 index 00000000000..ccd6fd080a9 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert.spec @@ -0,0 +1,47 @@ +# Test interaction between concurrent transactions performing +# create and insert in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-create-insert2.spec b/src/test/isolation/specs/ivm-create-insert2.spec new file mode 100644 index 00000000000..02cec85ae07 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert2.spec @@ -0,0 +1,54 @@ +# Test interaction between concurrent transactions performing +# create and insert in REPEATABLE READ isolation level +# +# Note: +# In this isolation level, it is possible that create_immv could +# create an inconsistent view not including effects of a concurrent +# transaction. So, an warning message is raised to suggest using it +# in READ COMMITTED or executing refresh_immv to make sure to +# make the view contents consistent. + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-create-insert3.spec b/src/test/isolation/specs/ivm-create-insert3.spec new file mode 100644 index 00000000000..19ce03185a4 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert3.spec @@ -0,0 +1,54 @@ +# Test interaction between concurrent transactions performing +# create and insert in SERIALIZABLE isolation level +# +# Note: +# In this isolation level, it is possible that create_immv could +# create an inconsistent view not including effects of a concurrent +# transaction. So, an warning message is raised to suggest using it +# in READ COMMITTED or executing refresh_immv to make sure to +# make the view contents consistent. + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert.spec b/src/test/isolation/specs/ivm-insert-insert.spec new file mode 100644 index 00000000000..b8f794ca191 --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert2.spec b/src/test/isolation/specs/ivm-insert-insert2.spec new file mode 100644 index 00000000000..ed086d1ba1e --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert2.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in REPEATABLE READ isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert3.spec b/src/test/isolation/specs/ivm-insert-insert3.spec new file mode 100644 index 00000000000..b18bd121033 --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert3.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in SERIALIZABLE isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert.spec b/src/test/isolation/specs/ivm-refresh-insert.spec new file mode 100644 index 00000000000..d7181251962 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert2.spec b/src/test/isolation/specs/ivm-refresh-insert2.spec new file mode 100644 index 00000000000..f2d1d5013f2 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert2.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in REPEATABLE READ isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert3.spec b/src/test/isolation/specs/ivm-refresh-insert3.spec new file mode 100644 index 00000000000..0ec2b1d1de0 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert3.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in SERIALIZABLE isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/regress/expected/incremental_matview.out b/src/test/regress/expected/incremental_matview.out new file mode 100644 index 00000000000..c7fd19fdca3 --- /dev/null +++ b/src/test/regress/expected/incremental_matview.out @@ -0,0 +1,667 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ERROR: materialized view "mv_ivm_1" has not been populated +HINT: Use the REFRESH MATERIALIZED VIEW command. +REFRESH MATERIALIZED VIEW mv_ivm_1; +NOTICE: could not create an index on materialized view "mv_ivm_1" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 17 +(1 row) + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 1 +(1 row) + +ROLLBACK; +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- DISTINCT not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT * FROM mv_base_a; +ERROR: DISTINCT is not supported on incrementally maintainable materialized view +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +NOTICE: could not create an index on materialized view "mv_ivm_func" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +NOTICE: could not create an index on materialized view "mv_ivm_no_tbl" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- result of materialized view have duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_duplicate" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 20 + 30 + 40 + 50 +(6 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +ROLLBACK; +-- aggregate not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +ERROR: aggregate function is not supported on incrementally maintainable materialized view +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +NOTICE: could not create an index on materialized view "mv_self" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +----+---- + 10 | 10 + 20 | 20 + 30 | 30 +(3 rows) + +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 30 | 30 + 40 | 40 + 200 | 200 +(3 rows) + +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 130 | 130 + 300 | 300 +(4 rows) + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 70 | 70 + 70 | 77 + 77 | 70 + 77 | 77 + 130 | 130 + 300 | 300 +(8 rows) + +ROLLBACK; +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY v1; + v1 | v2 +----+----- + 10 | 100 + 20 | 200 + 30 | 300 +(3 rows) + +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv ORDER BY v1; + v1 | v2 +------+----- + 10 | 100 + 11 | 100 + 1020 | 200 + 1020 | 222 +(4 rows) + +ROLLBACK; +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +NOTICE: created index "mv_ri_index" on materialized view "mv_ri" +SELECT * FROM mv_ri ORDER BY i1; + i1 | i2 +----+---- + 1 | 1 + 2 | 2 + 3 | 3 +(3 rows) + +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; + i1 | i2 +----+---- + 3 | 3 + 10 | 10 +(2 rows) + +ROLLBACK; +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | +(2 rows) + +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | 20 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i +--- +(0 rows) + +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; + i +--- + 1 + +(2 rows) + +ROLLBACK; +-- IMMV containing user defined type +BEGIN; +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: return type mytype is only a shell +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: argument type mytype is only a shell +LINE 1: CREATE FUNCTION mytype_out(mytype) + ^ +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +NOTICE: could not create an index on materialized view "mv_mytype" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + x +--- + 1 +(1 row) + +ROLLBACK; +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +ERROR: OUTER JOIN is not supported on incrementally maintainable materialized view +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +ERROR: CTE is not supported on incrementally maintainable materialized view +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +ERROR: ORDER BY clause is not supported on incrementally maintainable materialized view +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; +ERROR: HAVING clause is not supported on incrementally maintainable materialized view +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; +ERROR: mutable function is not supported on incrementally maintainable materialized view +HINT: functions must be marked IMMUTABLE +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; +ERROR: LIMIT/OFFSET clause is not supported on incrementally maintainable materialized view +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; +ERROR: DISTINCT is not supported on incrementally maintainable materialized view +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); +ERROR: TABLESAMPLE clause is not supported on incrementally maintainable materialized view +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; +ERROR: window functions are not supported on incrementally maintainable materialized view +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ERROR: inheritance parent is not supported on incrementally maintainable materialized view +ROLLBACK; +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; +ERROR: UNION/INTERSECT/EXCEPT statements are not supported on incrementally maintainable materialized view +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; +ERROR: empty target list is not supported on incrementally maintainable materialized view +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; +ERROR: FOR UPDATE/SHARE clause is not supported on incrementally maintainable materialized view +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; +ERROR: column name __ivm_count__ is not supported on incrementally maintainable materialized view +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; +ERROR: aggregate function is not supported on incrementally maintainable materialized view +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); +ERROR: VALUES is not supported on incrementally maintainable materialized view +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +NOTICE: role "regress_ivm_admin" does not exist, skipping +DROP USER IF EXISTS regress_ivm_user; +NOTICE: role "regress_ivm_user" does not exist, skipping +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +NOTICE: could not create an index on materialized view "ivm_rls" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user +(1 row) + +RESET SESSION AUTHORIZATION; +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user + 3 | baz | regress_ivm_user +(2 rows) + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +-- +(1 row) + +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+-------+------------------ + 2 | bar | regress_ivm_user + 3 | baz | regress_ivm_user + 6 | corge | regress_ivm_user +(3 rows) + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +NOTICE: could not create an index on materialized view "ivm_rls2" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +RESET SESSION AUTHORIZATION; +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +-- +(1 row) + +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + id | data | owner | num +----+-------+------------------+--------- + 2 | bar | regress_ivm_user | two + 3 | baz_2 | regress_ivm_user | three_2 + 6 | corge | regress_ivm_user | six +(3 rows) + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +NOTICE: could not create an index on materialized view "mv_update_same" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + i +--- + 2 +(1 row) + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +NOTICE: created index "mv_self_ref_index" on materialized view "mv_self_ref" +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; + a | b +----+---- + 11 | + 12 | 11 + 13 | 12 +(3 rows) + +ROLLBACK; +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; +NOTICE: created index "mv_idx3_index" on materialized view "mv_idx3" +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +NOTICE: could not create an index on materialized view "mv_idx4" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; +NOTICE: could not create an index on materialized view "mv_idx5" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); +NOTICE: could not create an index on materialized view "mv_idx6" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ERROR: data type json has no default operator class for access method "btree" +ROLLBACK; +-- cleanup +DROP TABLE rls_tbl CASCADE; +NOTICE: drop cascades to 2 other objects +DETAIL: drop cascades to materialized view ivm_rls +drop cascades to materialized view ivm_rls2 +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; +DROP TABLE mv_base_b CASCADE; +NOTICE: drop cascades to 3 other objects +DETAIL: drop cascades to materialized view mv_ivm_1 +drop cascades to view b_view +drop cascades to materialized view b_mview +DROP TABLE mv_base_a CASCADE; diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index 8fa0a6c47fb..7caca5f64fd 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -77,6 +77,7 @@ test: brin_bloom brin_multi # Another group of parallel tests # ---------- test: create_table_like alter_generic alter_operator misc async dbsize merge misc_functions nls sysviews tsrf tid tidscan tidrangescan collate.utf8 collate.icu.utf8 incremental_sort create_role without_overlaps generated_virtual +test: incremental_matview # collate.linux.utf8 and collate.icu.utf8 tests cannot be run in parallel with each other # psql depends on create_am diff --git a/src/test/regress/sql/incremental_matview.sql b/src/test/regress/sql/incremental_matview.sql new file mode 100644 index 00000000000..7313ad82f3e --- /dev/null +++ b/src/test/regress/sql/incremental_matview.sql @@ -0,0 +1,407 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); + +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +REFRESH MATERIALIZED VIEW mv_ivm_1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; + +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; +ROLLBACK; + +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- DISTINCT not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT * FROM mv_base_a; + +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; + + +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +ROLLBACK; + +-- result of materialized view have duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +ROLLBACK; + +-- aggregate not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; + +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +SELECT * FROM mv_self ORDER BY v1; +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; +SELECT * FROM mv_self ORDER BY v1; + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + +ROLLBACK; + +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +SELECT * FROM mv ORDER BY v1; +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; +SELECT * FROM mv ORDER BY v1; +ROLLBACK; + +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +SELECT * FROM mv_ri ORDER BY i1; +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; +ROLLBACK; + +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +-- IMMV containing user defined type +BEGIN; + +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); + +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; + +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); + +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); + +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + +ROLLBACK; + +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; + +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; + +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; + +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; + +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; + +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); + +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; + +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ROLLBACK; + +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; + +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; + +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; + +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; + +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; + +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); + +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +DROP USER IF EXISTS regress_ivm_user; +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; + +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); + +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; + +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; + +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; +RESET SESSION AUTHORIZATION; + +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +RESET SESSION AUTHORIZATION; + +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; +ROLLBACK; + +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); + +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; + +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; + +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); + +ROLLBACK; + +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ROLLBACK; + +-- cleanup + +DROP TABLE rls_tbl CASCADE; +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; + +DROP TABLE mv_base_b CASCADE; +DROP TABLE mv_base_a CASCADE; -- 2.43.0 --Multipart=_Fri__3_Jul_2026_19_11_16_+0900_CskxSIu_iGcDMEyM Content-Type: text/x-diff; name="v39-0006-Add-Incremental-View-Maintenance-support.patch" Content-Disposition: attachment; filename="v39-0006-Add-Incremental-View-Maintenance-support.patch" Content-Transfer-Encoding: 7bit ^ permalink raw reply [nested|flat] 78+ messages in thread
* [PATCH v39 7/8] Add regression tests for Incremental View Maintenance @ 2026-05-29 09:31 Yugo Nagata <[email protected]> 0 siblings, 0 replies; 78+ messages in thread From: Yugo Nagata @ 2026-05-29 09:31 UTC (permalink / raw) --- .../isolation/expected/ivm-create-insert.out | 285 ++++++++ .../isolation/expected/ivm-create-insert2.out | 305 ++++++++ .../isolation/expected/ivm-create-insert3.out | 305 ++++++++ .../isolation/expected/ivm-insert-insert.out | 497 +++++++++++++ .../isolation/expected/ivm-insert-insert2.out | 373 ++++++++++ .../isolation/expected/ivm-insert-insert3.out | 373 ++++++++++ .../isolation/expected/ivm-refresh-insert.out | 213 ++++++ .../expected/ivm-refresh-insert2.out | 191 +++++ .../expected/ivm-refresh-insert3.out | 191 +++++ src/test/isolation/isolation_schedule | 9 + .../isolation/specs/ivm-create-insert.spec | 47 ++ .../isolation/specs/ivm-create-insert2.spec | 54 ++ .../isolation/specs/ivm-create-insert3.spec | 54 ++ .../isolation/specs/ivm-insert-insert.spec | 62 ++ .../isolation/specs/ivm-insert-insert2.spec | 62 ++ .../isolation/specs/ivm-insert-insert3.spec | 62 ++ .../isolation/specs/ivm-refresh-insert.spec | 46 ++ .../isolation/specs/ivm-refresh-insert2.spec | 46 ++ .../isolation/specs/ivm-refresh-insert3.spec | 46 ++ .../regress/expected/incremental_matview.out | 667 ++++++++++++++++++ src/test/regress/parallel_schedule | 1 + src/test/regress/sql/incremental_matview.sql | 407 +++++++++++ 22 files changed, 4296 insertions(+) create mode 100644 src/test/isolation/expected/ivm-create-insert.out create mode 100644 src/test/isolation/expected/ivm-create-insert2.out create mode 100644 src/test/isolation/expected/ivm-create-insert3.out create mode 100644 src/test/isolation/expected/ivm-insert-insert.out create mode 100644 src/test/isolation/expected/ivm-insert-insert2.out create mode 100644 src/test/isolation/expected/ivm-insert-insert3.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert2.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert3.out create mode 100644 src/test/isolation/specs/ivm-create-insert.spec create mode 100644 src/test/isolation/specs/ivm-create-insert2.spec create mode 100644 src/test/isolation/specs/ivm-create-insert3.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert2.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert3.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert2.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert3.spec create mode 100644 src/test/regress/expected/incremental_matview.out create mode 100644 src/test/regress/sql/incremental_matview.sql diff --git a/src/test/isolation/expected/ivm-create-insert.out b/src/test/isolation/expected/ivm-create-insert.out new file mode 100644 index 00000000000..5da00043aba --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert.out @@ -0,0 +1,285 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-create-insert2.out b/src/test/isolation/expected/ivm-create-insert2.out new file mode 100644 index 00000000000..907d892c6d4 --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert2.out @@ -0,0 +1,305 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + diff --git a/src/test/isolation/expected/ivm-create-insert3.out b/src/test/isolation/expected/ivm-create-insert3.out new file mode 100644 index 00000000000..907d892c6d4 --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert3.out @@ -0,0 +1,305 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert.out b/src/test/isolation/expected/ivm-insert-insert.out new file mode 100644 index 00000000000..5ca4cfea677 --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert.out @@ -0,0 +1,497 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; <waiting ...> +step c1: COMMIT; +step update2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; <waiting ...> +step c1: COMMIT; +step update2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; <waiting ...> +step c2: COMMIT; +step update1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; <waiting ...> +step c2: COMMIT; +step update1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); <waiting ...> +step c1: COMMIT; +step insert2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); <waiting ...> +step c1: COMMIT; +step insert2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); <waiting ...> +step c2: COMMIT; +step insert1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); <waiting ...> +step c2: COMMIT; +step insert1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert2.out b/src/test/isolation/expected/ivm-insert-insert2.out new file mode 100644 index 00000000000..e1c66d4de5e --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert2.out @@ -0,0 +1,373 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert3.out b/src/test/isolation/expected/ivm-insert-insert3.out new file mode 100644 index 00000000000..e1c66d4de5e --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert3.out @@ -0,0 +1,373 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert.out b/src/test/isolation/expected/ivm-refresh-insert.out new file mode 100644 index 00000000000..a925938bf1c --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert.out @@ -0,0 +1,213 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert2.out b/src/test/isolation/expected/ivm-refresh-insert2.out new file mode 100644 index 00000000000..dc1b16ae34e --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert2.out @@ -0,0 +1,191 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert3.out b/src/test/isolation/expected/ivm-refresh-insert3.out new file mode 100644 index 00000000000..dc1b16ae34e --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert3.out @@ -0,0 +1,191 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/isolation_schedule b/src/test/isolation/isolation_schedule index b8ebe92553c..6b7e873b370 100644 --- a/src/test/isolation/isolation_schedule +++ b/src/test/isolation/isolation_schedule @@ -128,3 +128,12 @@ test: matview-write-skew test: lock-nowait test: for-portion-of test: ddl-dependency-locking +test: ivm-create-insert +test: ivm-create-insert2 +test: ivm-create-insert3 +test: ivm-insert-insert +test: ivm-insert-insert2 +test: ivm-insert-insert3 +test: ivm-refresh-insert +test: ivm-refresh-insert2 +test: ivm-refresh-insert3 diff --git a/src/test/isolation/specs/ivm-create-insert.spec b/src/test/isolation/specs/ivm-create-insert.spec new file mode 100644 index 00000000000..ccd6fd080a9 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert.spec @@ -0,0 +1,47 @@ +# Test interaction between concurrent transactions performing +# create and insert in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-create-insert2.spec b/src/test/isolation/specs/ivm-create-insert2.spec new file mode 100644 index 00000000000..02cec85ae07 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert2.spec @@ -0,0 +1,54 @@ +# Test interaction between concurrent transactions performing +# create and insert in REPEATABLE READ isolation level +# +# Note: +# In this isolation level, it is possible that create_immv could +# create an inconsistent view not including effects of a concurrent +# transaction. So, an warning message is raised to suggest using it +# in READ COMMITTED or executing refresh_immv to make sure to +# make the view contents consistent. + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-create-insert3.spec b/src/test/isolation/specs/ivm-create-insert3.spec new file mode 100644 index 00000000000..19ce03185a4 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert3.spec @@ -0,0 +1,54 @@ +# Test interaction between concurrent transactions performing +# create and insert in SERIALIZABLE isolation level +# +# Note: +# In this isolation level, it is possible that create_immv could +# create an inconsistent view not including effects of a concurrent +# transaction. So, an warning message is raised to suggest using it +# in READ COMMITTED or executing refresh_immv to make sure to +# make the view contents consistent. + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert.spec b/src/test/isolation/specs/ivm-insert-insert.spec new file mode 100644 index 00000000000..b8f794ca191 --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert2.spec b/src/test/isolation/specs/ivm-insert-insert2.spec new file mode 100644 index 00000000000..ed086d1ba1e --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert2.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in REPEATABLE READ isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert3.spec b/src/test/isolation/specs/ivm-insert-insert3.spec new file mode 100644 index 00000000000..b18bd121033 --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert3.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in SERIALIZABLE isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert.spec b/src/test/isolation/specs/ivm-refresh-insert.spec new file mode 100644 index 00000000000..d7181251962 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert2.spec b/src/test/isolation/specs/ivm-refresh-insert2.spec new file mode 100644 index 00000000000..f2d1d5013f2 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert2.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in REPEATABLE READ isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert3.spec b/src/test/isolation/specs/ivm-refresh-insert3.spec new file mode 100644 index 00000000000..0ec2b1d1de0 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert3.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in SERIALIZABLE isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/regress/expected/incremental_matview.out b/src/test/regress/expected/incremental_matview.out new file mode 100644 index 00000000000..c7fd19fdca3 --- /dev/null +++ b/src/test/regress/expected/incremental_matview.out @@ -0,0 +1,667 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ERROR: materialized view "mv_ivm_1" has not been populated +HINT: Use the REFRESH MATERIALIZED VIEW command. +REFRESH MATERIALIZED VIEW mv_ivm_1; +NOTICE: could not create an index on materialized view "mv_ivm_1" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 17 +(1 row) + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 1 +(1 row) + +ROLLBACK; +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- DISTINCT not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT * FROM mv_base_a; +ERROR: DISTINCT is not supported on incrementally maintainable materialized view +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +NOTICE: could not create an index on materialized view "mv_ivm_func" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +NOTICE: could not create an index on materialized view "mv_ivm_no_tbl" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- result of materialized view have duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_duplicate" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 20 + 30 + 40 + 50 +(6 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +ROLLBACK; +-- aggregate not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +ERROR: aggregate function is not supported on incrementally maintainable materialized view +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +NOTICE: could not create an index on materialized view "mv_self" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +----+---- + 10 | 10 + 20 | 20 + 30 | 30 +(3 rows) + +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 30 | 30 + 40 | 40 + 200 | 200 +(3 rows) + +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 130 | 130 + 300 | 300 +(4 rows) + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 70 | 70 + 70 | 77 + 77 | 70 + 77 | 77 + 130 | 130 + 300 | 300 +(8 rows) + +ROLLBACK; +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY v1; + v1 | v2 +----+----- + 10 | 100 + 20 | 200 + 30 | 300 +(3 rows) + +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv ORDER BY v1; + v1 | v2 +------+----- + 10 | 100 + 11 | 100 + 1020 | 200 + 1020 | 222 +(4 rows) + +ROLLBACK; +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +NOTICE: created index "mv_ri_index" on materialized view "mv_ri" +SELECT * FROM mv_ri ORDER BY i1; + i1 | i2 +----+---- + 1 | 1 + 2 | 2 + 3 | 3 +(3 rows) + +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; + i1 | i2 +----+---- + 3 | 3 + 10 | 10 +(2 rows) + +ROLLBACK; +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | +(2 rows) + +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | 20 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i +--- +(0 rows) + +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; + i +--- + 1 + +(2 rows) + +ROLLBACK; +-- IMMV containing user defined type +BEGIN; +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: return type mytype is only a shell +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: argument type mytype is only a shell +LINE 1: CREATE FUNCTION mytype_out(mytype) + ^ +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +NOTICE: could not create an index on materialized view "mv_mytype" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + x +--- + 1 +(1 row) + +ROLLBACK; +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +ERROR: OUTER JOIN is not supported on incrementally maintainable materialized view +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +ERROR: CTE is not supported on incrementally maintainable materialized view +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +ERROR: ORDER BY clause is not supported on incrementally maintainable materialized view +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; +ERROR: HAVING clause is not supported on incrementally maintainable materialized view +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; +ERROR: mutable function is not supported on incrementally maintainable materialized view +HINT: functions must be marked IMMUTABLE +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; +ERROR: LIMIT/OFFSET clause is not supported on incrementally maintainable materialized view +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; +ERROR: DISTINCT is not supported on incrementally maintainable materialized view +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); +ERROR: TABLESAMPLE clause is not supported on incrementally maintainable materialized view +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; +ERROR: window functions are not supported on incrementally maintainable materialized view +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ERROR: inheritance parent is not supported on incrementally maintainable materialized view +ROLLBACK; +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; +ERROR: UNION/INTERSECT/EXCEPT statements are not supported on incrementally maintainable materialized view +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; +ERROR: empty target list is not supported on incrementally maintainable materialized view +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; +ERROR: FOR UPDATE/SHARE clause is not supported on incrementally maintainable materialized view +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; +ERROR: column name __ivm_count__ is not supported on incrementally maintainable materialized view +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; +ERROR: aggregate function is not supported on incrementally maintainable materialized view +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); +ERROR: VALUES is not supported on incrementally maintainable materialized view +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +NOTICE: role "regress_ivm_admin" does not exist, skipping +DROP USER IF EXISTS regress_ivm_user; +NOTICE: role "regress_ivm_user" does not exist, skipping +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +NOTICE: could not create an index on materialized view "ivm_rls" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user +(1 row) + +RESET SESSION AUTHORIZATION; +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user + 3 | baz | regress_ivm_user +(2 rows) + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +-- +(1 row) + +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+-------+------------------ + 2 | bar | regress_ivm_user + 3 | baz | regress_ivm_user + 6 | corge | regress_ivm_user +(3 rows) + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +NOTICE: could not create an index on materialized view "ivm_rls2" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +RESET SESSION AUTHORIZATION; +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +-- +(1 row) + +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + id | data | owner | num +----+-------+------------------+--------- + 2 | bar | regress_ivm_user | two + 3 | baz_2 | regress_ivm_user | three_2 + 6 | corge | regress_ivm_user | six +(3 rows) + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +NOTICE: could not create an index on materialized view "mv_update_same" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + i +--- + 2 +(1 row) + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +NOTICE: created index "mv_self_ref_index" on materialized view "mv_self_ref" +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; + a | b +----+---- + 11 | + 12 | 11 + 13 | 12 +(3 rows) + +ROLLBACK; +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; +NOTICE: created index "mv_idx3_index" on materialized view "mv_idx3" +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +NOTICE: could not create an index on materialized view "mv_idx4" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; +NOTICE: could not create an index on materialized view "mv_idx5" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); +NOTICE: could not create an index on materialized view "mv_idx6" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ERROR: data type json has no default operator class for access method "btree" +ROLLBACK; +-- cleanup +DROP TABLE rls_tbl CASCADE; +NOTICE: drop cascades to 2 other objects +DETAIL: drop cascades to materialized view ivm_rls +drop cascades to materialized view ivm_rls2 +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; +DROP TABLE mv_base_b CASCADE; +NOTICE: drop cascades to 3 other objects +DETAIL: drop cascades to materialized view mv_ivm_1 +drop cascades to view b_view +drop cascades to materialized view b_mview +DROP TABLE mv_base_a CASCADE; diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index 8fa0a6c47fb..7caca5f64fd 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -77,6 +77,7 @@ test: brin_bloom brin_multi # Another group of parallel tests # ---------- test: create_table_like alter_generic alter_operator misc async dbsize merge misc_functions nls sysviews tsrf tid tidscan tidrangescan collate.utf8 collate.icu.utf8 incremental_sort create_role without_overlaps generated_virtual +test: incremental_matview # collate.linux.utf8 and collate.icu.utf8 tests cannot be run in parallel with each other # psql depends on create_am diff --git a/src/test/regress/sql/incremental_matview.sql b/src/test/regress/sql/incremental_matview.sql new file mode 100644 index 00000000000..7313ad82f3e --- /dev/null +++ b/src/test/regress/sql/incremental_matview.sql @@ -0,0 +1,407 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); + +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +REFRESH MATERIALIZED VIEW mv_ivm_1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; + +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; +ROLLBACK; + +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- DISTINCT not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT * FROM mv_base_a; + +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; + + +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +ROLLBACK; + +-- result of materialized view have duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +ROLLBACK; + +-- aggregate not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; + +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +SELECT * FROM mv_self ORDER BY v1; +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; +SELECT * FROM mv_self ORDER BY v1; + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + +ROLLBACK; + +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +SELECT * FROM mv ORDER BY v1; +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; +SELECT * FROM mv ORDER BY v1; +ROLLBACK; + +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +SELECT * FROM mv_ri ORDER BY i1; +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; +ROLLBACK; + +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +-- IMMV containing user defined type +BEGIN; + +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); + +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; + +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); + +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); + +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + +ROLLBACK; + +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; + +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; + +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; + +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; + +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; + +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); + +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; + +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ROLLBACK; + +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; + +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; + +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; + +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; + +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; + +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); + +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +DROP USER IF EXISTS regress_ivm_user; +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; + +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); + +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; + +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; + +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; +RESET SESSION AUTHORIZATION; + +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +RESET SESSION AUTHORIZATION; + +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; +ROLLBACK; + +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); + +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; + +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; + +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); + +ROLLBACK; + +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ROLLBACK; + +-- cleanup + +DROP TABLE rls_tbl CASCADE; +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; + +DROP TABLE mv_base_b CASCADE; +DROP TABLE mv_base_a CASCADE; -- 2.43.0 --Multipart=_Fri__3_Jul_2026_19_11_16_+0900_CskxSIu_iGcDMEyM Content-Type: text/x-diff; name="v39-0006-Add-Incremental-View-Maintenance-support.patch" Content-Disposition: attachment; filename="v39-0006-Add-Incremental-View-Maintenance-support.patch" Content-Transfer-Encoding: 7bit ^ permalink raw reply [nested|flat] 78+ messages in thread
* [PATCH v37 10/11] Add regression tests for Incremental View Maintenance @ 2026-05-29 09:31 Yugo Nagata <[email protected]> 0 siblings, 0 replies; 78+ messages in thread From: Yugo Nagata @ 2026-05-29 09:31 UTC (permalink / raw) --- src/test/isolation/isolation_schedule | 9 + .../regress/expected/incremental_matview.out | 1100 +++++++++++++++++ src/test/regress/parallel_schedule | 1 + src/test/regress/sql/incremental_matview.sql | 580 +++++++++ 4 files changed, 1690 insertions(+) create mode 100644 src/test/regress/expected/incremental_matview.out create mode 100644 src/test/regress/sql/incremental_matview.sql diff --git a/src/test/isolation/isolation_schedule b/src/test/isolation/isolation_schedule index 15c33fad4c5..111fd465207 100644 --- a/src/test/isolation/isolation_schedule +++ b/src/test/isolation/isolation_schedule @@ -127,3 +127,12 @@ test: matview-write-skew test: lock-nowait test: for-portion-of test: ddl-dependency-locking +test: ivm-create-insert +test: ivm-create-insert2 +test: ivm-create-insert3 +test: ivm-insert-insert +test: ivm-insert-insert2 +test: ivm-insert-insert3 +test: ivm-refresh-insert +test: ivm-refresh-insert2 +test: ivm-refresh-insert3 diff --git a/src/test/regress/expected/incremental_matview.out b/src/test/regress/expected/incremental_matview.out new file mode 100644 index 00000000000..f215aa88e48 --- /dev/null +++ b/src/test/regress/expected/incremental_matview.out @@ -0,0 +1,1100 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ERROR: materialized view "mv_ivm_1" has not been populated +HINT: Use the REFRESH MATERIALIZED VIEW command. +REFRESH MATERIALIZED VIEW mv_ivm_1; +NOTICE: could not create an index on materialized view "mv_ivm_1" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 17 +(1 row) + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 1 +(1 row) + +ROLLBACK; +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_rename_index" on materialized view "mv_ivm_rename" +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +ERROR: IVM column can not be renamed +DROP MATERIALIZED VIEW mv_ivm_rename; +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_unique_index" on materialized view "mv_ivm_unique" +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +ERROR: unique index creation on IVM columns is not supported +DROP MATERIALIZED VIEW mv_ivm_unique; +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +NOTICE: could not create an index on materialized view "mv_ivm_func" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +NOTICE: could not create an index on materialized view "mv_ivm_no_tbl" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_duplicate" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +NOTICE: created index "mv_ivm_distinct_index" on materialized view "mv_ivm_distinct" +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 20 + 30 + 40 + 50 +(6 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +ROLLBACK; +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 120 | 2 | 60.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+---------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 220 | 2 | 110.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 20 | 1 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 120 | 2 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; + sum | count +-----+------- +(0 rows) + +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; + i | sum | count +---+-----+------- +(0 rows) + +ROLLBACK; +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 150 | 5 | 30.0000000000000000 +(1 row) + +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 210 | 6 | 35.0000000000000000 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +NOTICE: created index "mv_ivm_avg_bug_index" on materialized view "mv_ivm_avg_bug" +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 3 | 3.3333333333333333 + 2 | 80 | 3 | 26.6666666666666667 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_min_max_index" on materialized view "mv_ivm_min_max" +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 10 + 2 | 20 | 20 + 3 | 30 | 30 + 4 | 40 | 40 + 5 | 50 | 50 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 12 + 2 | 20 | 22 + 3 | 30 | 32 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 11 | 12 + 2 | 20 | 22 + 3 | 30 | 31 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min_max" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 50 +(1 row) + +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 0 | 70 +(1 row) + +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 60 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + | +(1 row) + +ROLLBACK; +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min; + min +----- + 10 +(1 row) + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + min +----- + 20 +(1 row) + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; + min +----- + 30 +(1 row) + +ROLLBACK; +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | sum +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | b +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ERROR: too many column names were specified +ROLLBACK; +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +NOTICE: could not create an index on materialized view "mv_self" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +----+---- + 10 | 10 + 20 | 20 + 30 | 30 +(3 rows) + +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 30 | 30 + 40 | 40 + 200 | 200 +(3 rows) + +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 130 | 130 + 300 | 300 +(4 rows) + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 70 | 70 + 70 | 77 + 77 | 70 + 77 | 77 + 130 | 130 + 300 | 300 +(8 rows) + +ROLLBACK; +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY v1; + v1 | v2 +----+----- + 10 | 100 + 20 | 200 + 30 | 300 +(3 rows) + +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv ORDER BY v1; + v1 | v2 +------+----- + 10 | 100 + 11 | 100 + 1020 | 200 + 1020 | 222 +(4 rows) + +ROLLBACK; +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +NOTICE: created index "mv_ri_index" on materialized view "mv_ri" +SELECT * FROM mv_ri ORDER BY i1; + i1 | i2 +----+---- + 1 | 1 + 2 | 2 + 3 | 3 +(3 rows) + +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; + i1 | i2 +----+---- + 3 | 3 + 10 | 10 +(2 rows) + +ROLLBACK; +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | +(2 rows) + +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | 20 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i +--- +(0 rows) + +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; + i +--- + 1 + +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 30 + | 3 +(2 rows) + +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 300 + | 30 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 1 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 4 +(1 row) + +ROLLBACK; +-- IMMV containing user defined type +BEGIN; +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: return type mytype is only a shell +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: argument type mytype is only a shell +LINE 1: CREATE FUNCTION mytype_out(mytype) + ^ +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +NOTICE: could not create an index on materialized view "mv_mytype" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + x +--- + 1 +(1 row) + +ROLLBACK; +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +ERROR: OUTER JOIN is not supported on incrementally maintainable materialized view +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +ERROR: CTE is not supported on incrementally maintainable materialized view +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +ERROR: ORDER BY clause is not supported on incrementally maintainable materialized view +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; +ERROR: HAVING clause is not supported on incrementally maintainable materialized view +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; +ERROR: mutable function is not supported on incrementally maintainable materialized view +HINT: functions must be marked IMMUTABLE +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; +ERROR: LIMIT/OFFSET clause is not supported on incrementally maintainable materialized view +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; +ERROR: DISTINCT ON is not supported on incrementally maintainable materialized view +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); +ERROR: TABLESAMPLE clause is not supported on incrementally maintainable materialized view +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; +ERROR: window functions are not supported on incrementally maintainable materialized view +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +ERROR: aggregate function with FILTER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +ERROR: aggregate function with DISTINCT arguments is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +ERROR: aggregate function with ORDER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); +ERROR: GROUPING SETS, ROLLUP, or CUBE clauses is not supported on incrementally maintainable materialized view +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ERROR: inheritance parent is not supported on incrementally maintainable materialized view +ROLLBACK; +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; +ERROR: UNION/INTERSECT/EXCEPT statements are not supported on incrementally maintainable materialized view +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; +ERROR: empty target list is not supported on incrementally maintainable materialized view +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; +ERROR: FOR UPDATE/SHARE clause is not supported on incrementally maintainable materialized view +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; +ERROR: column name __ivm_count__ is not supported on incrementally maintainable materialized view +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; +ERROR: GROUP BY expression not appearing in select list is not supported on incrementally maintainable materialized view +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); +ERROR: VALUES is not supported on incrementally maintainable materialized view +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +NOTICE: role "regress_ivm_admin" does not exist, skipping +DROP USER IF EXISTS regress_ivm_user; +NOTICE: role "regress_ivm_user" does not exist, skipping +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +NOTICE: could not create an index on materialized view "ivm_rls" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user +(1 row) + +RESET SESSION AUTHORIZATION; +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user + 3 | baz | regress_ivm_user +(2 rows) + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +-- +(1 row) + +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+-------+------------------ + 2 | bar | regress_ivm_user + 3 | baz | regress_ivm_user + 6 | corge | regress_ivm_user +(3 rows) + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +NOTICE: could not create an index on materialized view "ivm_rls2" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +RESET SESSION AUTHORIZATION; +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +-- +(1 row) + +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + id | data | owner | num +----+-------+------------------+--------- + 2 | bar | regress_ivm_user | two + 3 | baz_2 | regress_ivm_user | three_2 + 6 | corge | regress_ivm_user | six +(3 rows) + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +NOTICE: could not create an index on materialized view "mv_update_same" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + i +--- + 2 +(1 row) + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +NOTICE: created index "mv_self_ref_index" on materialized view "mv_self_ref" +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; + a | b +----+---- + 11 | + 12 | 11 + 13 | 12 +(3 rows) + +ROLLBACK; +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; +NOTICE: created index "mv_idx1_index" on materialized view "mv_idx1" +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; +NOTICE: created index "mv_idx2_index" on materialized view "mv_idx2" +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; +NOTICE: created index "mv_idx3_index" on materialized view "mv_idx3" +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +NOTICE: could not create an index on materialized view "mv_idx4" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; +NOTICE: could not create an index on materialized view "mv_idx5" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); +NOTICE: could not create an index on materialized view "mv_idx6" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ERROR: data type json has no default operator class for access method "btree" +ROLLBACK; +-- cleanup +DROP TABLE rls_tbl CASCADE; +NOTICE: drop cascades to 2 other objects +DETAIL: drop cascades to materialized view ivm_rls +drop cascades to materialized view ivm_rls2 +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; +DROP TABLE mv_base_b CASCADE; +NOTICE: drop cascades to 3 other objects +DETAIL: drop cascades to materialized view mv_ivm_1 +drop cascades to view b_view +drop cascades to materialized view b_mview +DROP TABLE mv_base_a CASCADE; diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index 8fa0a6c47fb..7caca5f64fd 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -77,6 +77,7 @@ test: brin_bloom brin_multi # Another group of parallel tests # ---------- test: create_table_like alter_generic alter_operator misc async dbsize merge misc_functions nls sysviews tsrf tid tidscan tidrangescan collate.utf8 collate.icu.utf8 incremental_sort create_role without_overlaps generated_virtual +test: incremental_matview # collate.linux.utf8 and collate.icu.utf8 tests cannot be run in parallel with each other # psql depends on create_am diff --git a/src/test/regress/sql/incremental_matview.sql b/src/test/regress/sql/incremental_matview.sql new file mode 100644 index 00000000000..2d55c393d6f --- /dev/null +++ b/src/test/regress/sql/incremental_matview.sql @@ -0,0 +1,580 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); + +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +REFRESH MATERIALIZED VIEW mv_ivm_1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; + +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; +ROLLBACK; + +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +DROP MATERIALIZED VIEW mv_ivm_rename; + +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +DROP MATERIALIZED VIEW mv_ivm_unique; + +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; + + +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +ROLLBACK; + +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +ROLLBACK; + +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +ROLLBACK; + +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +ROLLBACK; + +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +ROLLBACK; + +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min; + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); + +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; +ROLLBACK; + +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +SELECT * FROM mv_self ORDER BY v1; +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; +SELECT * FROM mv_self ORDER BY v1; + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + +ROLLBACK; + +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +SELECT * FROM mv ORDER BY v1; +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; +SELECT * FROM mv ORDER BY v1; +ROLLBACK; + +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +SELECT * FROM mv_ri ORDER BY i1; +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; +ROLLBACK; + +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +-- IMMV containing user defined type +BEGIN; + +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); + +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; + +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); + +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); + +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + +ROLLBACK; + +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; + +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; + +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; + +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; + +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; + +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); + +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; + +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); + +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ROLLBACK; + +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; + +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; + +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; + +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; + +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; + +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; + +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); + +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +DROP USER IF EXISTS regress_ivm_user; +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; + +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); + +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; + +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; + +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; +RESET SESSION AUTHORIZATION; + +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +RESET SESSION AUTHORIZATION; + +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; +ROLLBACK; + +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); + +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; + +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; + +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; + +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; + +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); + +ROLLBACK; + +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ROLLBACK; + +-- cleanup + +DROP TABLE rls_tbl CASCADE; +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; + +DROP TABLE mv_base_b CASCADE; +DROP TABLE mv_base_a CASCADE; -- 2.43.0 --Multipart=_Fri__29_May_2026_23_14_17_+0900_Te0o73X2VqYK57Gd Content-Type: text/x-diff; name="v37-0009-Add-support-for-min-max-aggregates-for-IVM.patch" Content-Disposition: attachment; filename="v37-0009-Add-support-for-min-max-aggregates-for-IVM.patch" Content-Transfer-Encoding: 7bit ^ permalink raw reply [nested|flat] 78+ messages in thread
* [PATCH v39 7/8] Add regression tests for Incremental View Maintenance @ 2026-05-29 09:31 Yugo Nagata <[email protected]> 0 siblings, 0 replies; 78+ messages in thread From: Yugo Nagata @ 2026-05-29 09:31 UTC (permalink / raw) --- .../isolation/expected/ivm-create-insert.out | 285 ++++++++ .../isolation/expected/ivm-create-insert2.out | 305 ++++++++ .../isolation/expected/ivm-create-insert3.out | 305 ++++++++ .../isolation/expected/ivm-insert-insert.out | 497 +++++++++++++ .../isolation/expected/ivm-insert-insert2.out | 373 ++++++++++ .../isolation/expected/ivm-insert-insert3.out | 373 ++++++++++ .../isolation/expected/ivm-refresh-insert.out | 213 ++++++ .../expected/ivm-refresh-insert2.out | 191 +++++ .../expected/ivm-refresh-insert3.out | 191 +++++ src/test/isolation/isolation_schedule | 9 + .../isolation/specs/ivm-create-insert.spec | 47 ++ .../isolation/specs/ivm-create-insert2.spec | 54 ++ .../isolation/specs/ivm-create-insert3.spec | 54 ++ .../isolation/specs/ivm-insert-insert.spec | 62 ++ .../isolation/specs/ivm-insert-insert2.spec | 62 ++ .../isolation/specs/ivm-insert-insert3.spec | 62 ++ .../isolation/specs/ivm-refresh-insert.spec | 46 ++ .../isolation/specs/ivm-refresh-insert2.spec | 46 ++ .../isolation/specs/ivm-refresh-insert3.spec | 46 ++ .../regress/expected/incremental_matview.out | 667 ++++++++++++++++++ src/test/regress/parallel_schedule | 1 + src/test/regress/sql/incremental_matview.sql | 407 +++++++++++ 22 files changed, 4296 insertions(+) create mode 100644 src/test/isolation/expected/ivm-create-insert.out create mode 100644 src/test/isolation/expected/ivm-create-insert2.out create mode 100644 src/test/isolation/expected/ivm-create-insert3.out create mode 100644 src/test/isolation/expected/ivm-insert-insert.out create mode 100644 src/test/isolation/expected/ivm-insert-insert2.out create mode 100644 src/test/isolation/expected/ivm-insert-insert3.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert2.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert3.out create mode 100644 src/test/isolation/specs/ivm-create-insert.spec create mode 100644 src/test/isolation/specs/ivm-create-insert2.spec create mode 100644 src/test/isolation/specs/ivm-create-insert3.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert2.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert3.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert2.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert3.spec create mode 100644 src/test/regress/expected/incremental_matview.out create mode 100644 src/test/regress/sql/incremental_matview.sql diff --git a/src/test/isolation/expected/ivm-create-insert.out b/src/test/isolation/expected/ivm-create-insert.out new file mode 100644 index 00000000000..5da00043aba --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert.out @@ -0,0 +1,285 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-create-insert2.out b/src/test/isolation/expected/ivm-create-insert2.out new file mode 100644 index 00000000000..907d892c6d4 --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert2.out @@ -0,0 +1,305 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + diff --git a/src/test/isolation/expected/ivm-create-insert3.out b/src/test/isolation/expected/ivm-create-insert3.out new file mode 100644 index 00000000000..907d892c6d4 --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert3.out @@ -0,0 +1,305 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert.out b/src/test/isolation/expected/ivm-insert-insert.out new file mode 100644 index 00000000000..5ca4cfea677 --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert.out @@ -0,0 +1,497 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; <waiting ...> +step c1: COMMIT; +step update2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; <waiting ...> +step c1: COMMIT; +step update2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; <waiting ...> +step c2: COMMIT; +step update1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; <waiting ...> +step c2: COMMIT; +step update1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); <waiting ...> +step c1: COMMIT; +step insert2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); <waiting ...> +step c1: COMMIT; +step insert2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); <waiting ...> +step c2: COMMIT; +step insert1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); <waiting ...> +step c2: COMMIT; +step insert1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert2.out b/src/test/isolation/expected/ivm-insert-insert2.out new file mode 100644 index 00000000000..e1c66d4de5e --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert2.out @@ -0,0 +1,373 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert3.out b/src/test/isolation/expected/ivm-insert-insert3.out new file mode 100644 index 00000000000..e1c66d4de5e --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert3.out @@ -0,0 +1,373 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert.out b/src/test/isolation/expected/ivm-refresh-insert.out new file mode 100644 index 00000000000..a925938bf1c --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert.out @@ -0,0 +1,213 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert2.out b/src/test/isolation/expected/ivm-refresh-insert2.out new file mode 100644 index 00000000000..dc1b16ae34e --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert2.out @@ -0,0 +1,191 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert3.out b/src/test/isolation/expected/ivm-refresh-insert3.out new file mode 100644 index 00000000000..dc1b16ae34e --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert3.out @@ -0,0 +1,191 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/isolation_schedule b/src/test/isolation/isolation_schedule index b8ebe92553c..6b7e873b370 100644 --- a/src/test/isolation/isolation_schedule +++ b/src/test/isolation/isolation_schedule @@ -128,3 +128,12 @@ test: matview-write-skew test: lock-nowait test: for-portion-of test: ddl-dependency-locking +test: ivm-create-insert +test: ivm-create-insert2 +test: ivm-create-insert3 +test: ivm-insert-insert +test: ivm-insert-insert2 +test: ivm-insert-insert3 +test: ivm-refresh-insert +test: ivm-refresh-insert2 +test: ivm-refresh-insert3 diff --git a/src/test/isolation/specs/ivm-create-insert.spec b/src/test/isolation/specs/ivm-create-insert.spec new file mode 100644 index 00000000000..ccd6fd080a9 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert.spec @@ -0,0 +1,47 @@ +# Test interaction between concurrent transactions performing +# create and insert in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-create-insert2.spec b/src/test/isolation/specs/ivm-create-insert2.spec new file mode 100644 index 00000000000..02cec85ae07 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert2.spec @@ -0,0 +1,54 @@ +# Test interaction between concurrent transactions performing +# create and insert in REPEATABLE READ isolation level +# +# Note: +# In this isolation level, it is possible that create_immv could +# create an inconsistent view not including effects of a concurrent +# transaction. So, an warning message is raised to suggest using it +# in READ COMMITTED or executing refresh_immv to make sure to +# make the view contents consistent. + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-create-insert3.spec b/src/test/isolation/specs/ivm-create-insert3.spec new file mode 100644 index 00000000000..19ce03185a4 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert3.spec @@ -0,0 +1,54 @@ +# Test interaction between concurrent transactions performing +# create and insert in SERIALIZABLE isolation level +# +# Note: +# In this isolation level, it is possible that create_immv could +# create an inconsistent view not including effects of a concurrent +# transaction. So, an warning message is raised to suggest using it +# in READ COMMITTED or executing refresh_immv to make sure to +# make the view contents consistent. + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert.spec b/src/test/isolation/specs/ivm-insert-insert.spec new file mode 100644 index 00000000000..b8f794ca191 --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert2.spec b/src/test/isolation/specs/ivm-insert-insert2.spec new file mode 100644 index 00000000000..ed086d1ba1e --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert2.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in REPEATABLE READ isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert3.spec b/src/test/isolation/specs/ivm-insert-insert3.spec new file mode 100644 index 00000000000..b18bd121033 --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert3.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in SERIALIZABLE isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert.spec b/src/test/isolation/specs/ivm-refresh-insert.spec new file mode 100644 index 00000000000..d7181251962 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert2.spec b/src/test/isolation/specs/ivm-refresh-insert2.spec new file mode 100644 index 00000000000..f2d1d5013f2 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert2.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in REPEATABLE READ isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert3.spec b/src/test/isolation/specs/ivm-refresh-insert3.spec new file mode 100644 index 00000000000..0ec2b1d1de0 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert3.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in SERIALIZABLE isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/regress/expected/incremental_matview.out b/src/test/regress/expected/incremental_matview.out new file mode 100644 index 00000000000..c7fd19fdca3 --- /dev/null +++ b/src/test/regress/expected/incremental_matview.out @@ -0,0 +1,667 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ERROR: materialized view "mv_ivm_1" has not been populated +HINT: Use the REFRESH MATERIALIZED VIEW command. +REFRESH MATERIALIZED VIEW mv_ivm_1; +NOTICE: could not create an index on materialized view "mv_ivm_1" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 17 +(1 row) + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 1 +(1 row) + +ROLLBACK; +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- DISTINCT not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT * FROM mv_base_a; +ERROR: DISTINCT is not supported on incrementally maintainable materialized view +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +NOTICE: could not create an index on materialized view "mv_ivm_func" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +NOTICE: could not create an index on materialized view "mv_ivm_no_tbl" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- result of materialized view have duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_duplicate" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 20 + 30 + 40 + 50 +(6 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +ROLLBACK; +-- aggregate not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +ERROR: aggregate function is not supported on incrementally maintainable materialized view +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +NOTICE: could not create an index on materialized view "mv_self" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +----+---- + 10 | 10 + 20 | 20 + 30 | 30 +(3 rows) + +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 30 | 30 + 40 | 40 + 200 | 200 +(3 rows) + +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 130 | 130 + 300 | 300 +(4 rows) + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 70 | 70 + 70 | 77 + 77 | 70 + 77 | 77 + 130 | 130 + 300 | 300 +(8 rows) + +ROLLBACK; +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY v1; + v1 | v2 +----+----- + 10 | 100 + 20 | 200 + 30 | 300 +(3 rows) + +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv ORDER BY v1; + v1 | v2 +------+----- + 10 | 100 + 11 | 100 + 1020 | 200 + 1020 | 222 +(4 rows) + +ROLLBACK; +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +NOTICE: created index "mv_ri_index" on materialized view "mv_ri" +SELECT * FROM mv_ri ORDER BY i1; + i1 | i2 +----+---- + 1 | 1 + 2 | 2 + 3 | 3 +(3 rows) + +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; + i1 | i2 +----+---- + 3 | 3 + 10 | 10 +(2 rows) + +ROLLBACK; +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | +(2 rows) + +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | 20 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i +--- +(0 rows) + +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; + i +--- + 1 + +(2 rows) + +ROLLBACK; +-- IMMV containing user defined type +BEGIN; +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: return type mytype is only a shell +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: argument type mytype is only a shell +LINE 1: CREATE FUNCTION mytype_out(mytype) + ^ +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +NOTICE: could not create an index on materialized view "mv_mytype" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + x +--- + 1 +(1 row) + +ROLLBACK; +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +ERROR: OUTER JOIN is not supported on incrementally maintainable materialized view +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +ERROR: CTE is not supported on incrementally maintainable materialized view +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +ERROR: ORDER BY clause is not supported on incrementally maintainable materialized view +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; +ERROR: HAVING clause is not supported on incrementally maintainable materialized view +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; +ERROR: mutable function is not supported on incrementally maintainable materialized view +HINT: functions must be marked IMMUTABLE +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; +ERROR: LIMIT/OFFSET clause is not supported on incrementally maintainable materialized view +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; +ERROR: DISTINCT is not supported on incrementally maintainable materialized view +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); +ERROR: TABLESAMPLE clause is not supported on incrementally maintainable materialized view +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; +ERROR: window functions are not supported on incrementally maintainable materialized view +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ERROR: inheritance parent is not supported on incrementally maintainable materialized view +ROLLBACK; +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; +ERROR: UNION/INTERSECT/EXCEPT statements are not supported on incrementally maintainable materialized view +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; +ERROR: empty target list is not supported on incrementally maintainable materialized view +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; +ERROR: FOR UPDATE/SHARE clause is not supported on incrementally maintainable materialized view +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; +ERROR: column name __ivm_count__ is not supported on incrementally maintainable materialized view +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; +ERROR: aggregate function is not supported on incrementally maintainable materialized view +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); +ERROR: VALUES is not supported on incrementally maintainable materialized view +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +NOTICE: role "regress_ivm_admin" does not exist, skipping +DROP USER IF EXISTS regress_ivm_user; +NOTICE: role "regress_ivm_user" does not exist, skipping +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +NOTICE: could not create an index on materialized view "ivm_rls" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user +(1 row) + +RESET SESSION AUTHORIZATION; +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user + 3 | baz | regress_ivm_user +(2 rows) + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +-- +(1 row) + +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+-------+------------------ + 2 | bar | regress_ivm_user + 3 | baz | regress_ivm_user + 6 | corge | regress_ivm_user +(3 rows) + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +NOTICE: could not create an index on materialized view "ivm_rls2" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +RESET SESSION AUTHORIZATION; +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +-- +(1 row) + +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + id | data | owner | num +----+-------+------------------+--------- + 2 | bar | regress_ivm_user | two + 3 | baz_2 | regress_ivm_user | three_2 + 6 | corge | regress_ivm_user | six +(3 rows) + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +NOTICE: could not create an index on materialized view "mv_update_same" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + i +--- + 2 +(1 row) + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +NOTICE: created index "mv_self_ref_index" on materialized view "mv_self_ref" +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; + a | b +----+---- + 11 | + 12 | 11 + 13 | 12 +(3 rows) + +ROLLBACK; +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; +NOTICE: created index "mv_idx3_index" on materialized view "mv_idx3" +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +NOTICE: could not create an index on materialized view "mv_idx4" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; +NOTICE: could not create an index on materialized view "mv_idx5" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); +NOTICE: could not create an index on materialized view "mv_idx6" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ERROR: data type json has no default operator class for access method "btree" +ROLLBACK; +-- cleanup +DROP TABLE rls_tbl CASCADE; +NOTICE: drop cascades to 2 other objects +DETAIL: drop cascades to materialized view ivm_rls +drop cascades to materialized view ivm_rls2 +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; +DROP TABLE mv_base_b CASCADE; +NOTICE: drop cascades to 3 other objects +DETAIL: drop cascades to materialized view mv_ivm_1 +drop cascades to view b_view +drop cascades to materialized view b_mview +DROP TABLE mv_base_a CASCADE; diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index 8fa0a6c47fb..7caca5f64fd 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -77,6 +77,7 @@ test: brin_bloom brin_multi # Another group of parallel tests # ---------- test: create_table_like alter_generic alter_operator misc async dbsize merge misc_functions nls sysviews tsrf tid tidscan tidrangescan collate.utf8 collate.icu.utf8 incremental_sort create_role without_overlaps generated_virtual +test: incremental_matview # collate.linux.utf8 and collate.icu.utf8 tests cannot be run in parallel with each other # psql depends on create_am diff --git a/src/test/regress/sql/incremental_matview.sql b/src/test/regress/sql/incremental_matview.sql new file mode 100644 index 00000000000..7313ad82f3e --- /dev/null +++ b/src/test/regress/sql/incremental_matview.sql @@ -0,0 +1,407 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); + +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +REFRESH MATERIALIZED VIEW mv_ivm_1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; + +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; +ROLLBACK; + +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- DISTINCT not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT * FROM mv_base_a; + +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; + + +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +ROLLBACK; + +-- result of materialized view have duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +ROLLBACK; + +-- aggregate not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; + +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +SELECT * FROM mv_self ORDER BY v1; +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; +SELECT * FROM mv_self ORDER BY v1; + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + +ROLLBACK; + +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +SELECT * FROM mv ORDER BY v1; +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; +SELECT * FROM mv ORDER BY v1; +ROLLBACK; + +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +SELECT * FROM mv_ri ORDER BY i1; +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; +ROLLBACK; + +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +-- IMMV containing user defined type +BEGIN; + +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); + +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; + +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); + +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); + +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + +ROLLBACK; + +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; + +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; + +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; + +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; + +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; + +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); + +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; + +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ROLLBACK; + +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; + +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; + +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; + +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; + +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; + +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); + +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +DROP USER IF EXISTS regress_ivm_user; +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; + +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); + +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; + +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; + +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; +RESET SESSION AUTHORIZATION; + +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +RESET SESSION AUTHORIZATION; + +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; +ROLLBACK; + +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); + +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; + +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; + +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); + +ROLLBACK; + +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ROLLBACK; + +-- cleanup + +DROP TABLE rls_tbl CASCADE; +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; + +DROP TABLE mv_base_b CASCADE; +DROP TABLE mv_base_a CASCADE; -- 2.43.0 --Multipart=_Fri__3_Jul_2026_19_11_16_+0900_CskxSIu_iGcDMEyM Content-Type: text/x-diff; name="v39-0006-Add-Incremental-View-Maintenance-support.patch" Content-Disposition: attachment; filename="v39-0006-Add-Incremental-View-Maintenance-support.patch" Content-Transfer-Encoding: 7bit ^ permalink raw reply [nested|flat] 78+ messages in thread
* [PATCH v39 7/8] Add regression tests for Incremental View Maintenance @ 2026-05-29 09:31 Yugo Nagata <[email protected]> 0 siblings, 0 replies; 78+ messages in thread From: Yugo Nagata @ 2026-05-29 09:31 UTC (permalink / raw) --- .../isolation/expected/ivm-create-insert.out | 285 ++++++++ .../isolation/expected/ivm-create-insert2.out | 305 ++++++++ .../isolation/expected/ivm-create-insert3.out | 305 ++++++++ .../isolation/expected/ivm-insert-insert.out | 497 +++++++++++++ .../isolation/expected/ivm-insert-insert2.out | 373 ++++++++++ .../isolation/expected/ivm-insert-insert3.out | 373 ++++++++++ .../isolation/expected/ivm-refresh-insert.out | 213 ++++++ .../expected/ivm-refresh-insert2.out | 191 +++++ .../expected/ivm-refresh-insert3.out | 191 +++++ src/test/isolation/isolation_schedule | 9 + .../isolation/specs/ivm-create-insert.spec | 47 ++ .../isolation/specs/ivm-create-insert2.spec | 54 ++ .../isolation/specs/ivm-create-insert3.spec | 54 ++ .../isolation/specs/ivm-insert-insert.spec | 62 ++ .../isolation/specs/ivm-insert-insert2.spec | 62 ++ .../isolation/specs/ivm-insert-insert3.spec | 62 ++ .../isolation/specs/ivm-refresh-insert.spec | 46 ++ .../isolation/specs/ivm-refresh-insert2.spec | 46 ++ .../isolation/specs/ivm-refresh-insert3.spec | 46 ++ .../regress/expected/incremental_matview.out | 667 ++++++++++++++++++ src/test/regress/parallel_schedule | 1 + src/test/regress/sql/incremental_matview.sql | 407 +++++++++++ 22 files changed, 4296 insertions(+) create mode 100644 src/test/isolation/expected/ivm-create-insert.out create mode 100644 src/test/isolation/expected/ivm-create-insert2.out create mode 100644 src/test/isolation/expected/ivm-create-insert3.out create mode 100644 src/test/isolation/expected/ivm-insert-insert.out create mode 100644 src/test/isolation/expected/ivm-insert-insert2.out create mode 100644 src/test/isolation/expected/ivm-insert-insert3.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert2.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert3.out create mode 100644 src/test/isolation/specs/ivm-create-insert.spec create mode 100644 src/test/isolation/specs/ivm-create-insert2.spec create mode 100644 src/test/isolation/specs/ivm-create-insert3.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert2.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert3.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert2.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert3.spec create mode 100644 src/test/regress/expected/incremental_matview.out create mode 100644 src/test/regress/sql/incremental_matview.sql diff --git a/src/test/isolation/expected/ivm-create-insert.out b/src/test/isolation/expected/ivm-create-insert.out new file mode 100644 index 00000000000..5da00043aba --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert.out @@ -0,0 +1,285 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-create-insert2.out b/src/test/isolation/expected/ivm-create-insert2.out new file mode 100644 index 00000000000..907d892c6d4 --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert2.out @@ -0,0 +1,305 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + diff --git a/src/test/isolation/expected/ivm-create-insert3.out b/src/test/isolation/expected/ivm-create-insert3.out new file mode 100644 index 00000000000..907d892c6d4 --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert3.out @@ -0,0 +1,305 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert.out b/src/test/isolation/expected/ivm-insert-insert.out new file mode 100644 index 00000000000..5ca4cfea677 --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert.out @@ -0,0 +1,497 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; <waiting ...> +step c1: COMMIT; +step update2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; <waiting ...> +step c1: COMMIT; +step update2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; <waiting ...> +step c2: COMMIT; +step update1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; <waiting ...> +step c2: COMMIT; +step update1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); <waiting ...> +step c1: COMMIT; +step insert2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); <waiting ...> +step c1: COMMIT; +step insert2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); <waiting ...> +step c2: COMMIT; +step insert1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); <waiting ...> +step c2: COMMIT; +step insert1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert2.out b/src/test/isolation/expected/ivm-insert-insert2.out new file mode 100644 index 00000000000..e1c66d4de5e --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert2.out @@ -0,0 +1,373 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert3.out b/src/test/isolation/expected/ivm-insert-insert3.out new file mode 100644 index 00000000000..e1c66d4de5e --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert3.out @@ -0,0 +1,373 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert.out b/src/test/isolation/expected/ivm-refresh-insert.out new file mode 100644 index 00000000000..a925938bf1c --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert.out @@ -0,0 +1,213 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert2.out b/src/test/isolation/expected/ivm-refresh-insert2.out new file mode 100644 index 00000000000..dc1b16ae34e --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert2.out @@ -0,0 +1,191 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert3.out b/src/test/isolation/expected/ivm-refresh-insert3.out new file mode 100644 index 00000000000..dc1b16ae34e --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert3.out @@ -0,0 +1,191 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/isolation_schedule b/src/test/isolation/isolation_schedule index b8ebe92553c..6b7e873b370 100644 --- a/src/test/isolation/isolation_schedule +++ b/src/test/isolation/isolation_schedule @@ -128,3 +128,12 @@ test: matview-write-skew test: lock-nowait test: for-portion-of test: ddl-dependency-locking +test: ivm-create-insert +test: ivm-create-insert2 +test: ivm-create-insert3 +test: ivm-insert-insert +test: ivm-insert-insert2 +test: ivm-insert-insert3 +test: ivm-refresh-insert +test: ivm-refresh-insert2 +test: ivm-refresh-insert3 diff --git a/src/test/isolation/specs/ivm-create-insert.spec b/src/test/isolation/specs/ivm-create-insert.spec new file mode 100644 index 00000000000..ccd6fd080a9 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert.spec @@ -0,0 +1,47 @@ +# Test interaction between concurrent transactions performing +# create and insert in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-create-insert2.spec b/src/test/isolation/specs/ivm-create-insert2.spec new file mode 100644 index 00000000000..02cec85ae07 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert2.spec @@ -0,0 +1,54 @@ +# Test interaction between concurrent transactions performing +# create and insert in REPEATABLE READ isolation level +# +# Note: +# In this isolation level, it is possible that create_immv could +# create an inconsistent view not including effects of a concurrent +# transaction. So, an warning message is raised to suggest using it +# in READ COMMITTED or executing refresh_immv to make sure to +# make the view contents consistent. + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-create-insert3.spec b/src/test/isolation/specs/ivm-create-insert3.spec new file mode 100644 index 00000000000..19ce03185a4 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert3.spec @@ -0,0 +1,54 @@ +# Test interaction between concurrent transactions performing +# create and insert in SERIALIZABLE isolation level +# +# Note: +# In this isolation level, it is possible that create_immv could +# create an inconsistent view not including effects of a concurrent +# transaction. So, an warning message is raised to suggest using it +# in READ COMMITTED or executing refresh_immv to make sure to +# make the view contents consistent. + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert.spec b/src/test/isolation/specs/ivm-insert-insert.spec new file mode 100644 index 00000000000..b8f794ca191 --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert2.spec b/src/test/isolation/specs/ivm-insert-insert2.spec new file mode 100644 index 00000000000..ed086d1ba1e --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert2.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in REPEATABLE READ isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert3.spec b/src/test/isolation/specs/ivm-insert-insert3.spec new file mode 100644 index 00000000000..b18bd121033 --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert3.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in SERIALIZABLE isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert.spec b/src/test/isolation/specs/ivm-refresh-insert.spec new file mode 100644 index 00000000000..d7181251962 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert2.spec b/src/test/isolation/specs/ivm-refresh-insert2.spec new file mode 100644 index 00000000000..f2d1d5013f2 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert2.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in REPEATABLE READ isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert3.spec b/src/test/isolation/specs/ivm-refresh-insert3.spec new file mode 100644 index 00000000000..0ec2b1d1de0 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert3.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in SERIALIZABLE isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/regress/expected/incremental_matview.out b/src/test/regress/expected/incremental_matview.out new file mode 100644 index 00000000000..c7fd19fdca3 --- /dev/null +++ b/src/test/regress/expected/incremental_matview.out @@ -0,0 +1,667 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ERROR: materialized view "mv_ivm_1" has not been populated +HINT: Use the REFRESH MATERIALIZED VIEW command. +REFRESH MATERIALIZED VIEW mv_ivm_1; +NOTICE: could not create an index on materialized view "mv_ivm_1" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 17 +(1 row) + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 1 +(1 row) + +ROLLBACK; +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- DISTINCT not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT * FROM mv_base_a; +ERROR: DISTINCT is not supported on incrementally maintainable materialized view +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +NOTICE: could not create an index on materialized view "mv_ivm_func" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +NOTICE: could not create an index on materialized view "mv_ivm_no_tbl" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- result of materialized view have duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_duplicate" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 20 + 30 + 40 + 50 +(6 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +ROLLBACK; +-- aggregate not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +ERROR: aggregate function is not supported on incrementally maintainable materialized view +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +NOTICE: could not create an index on materialized view "mv_self" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +----+---- + 10 | 10 + 20 | 20 + 30 | 30 +(3 rows) + +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 30 | 30 + 40 | 40 + 200 | 200 +(3 rows) + +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 130 | 130 + 300 | 300 +(4 rows) + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 70 | 70 + 70 | 77 + 77 | 70 + 77 | 77 + 130 | 130 + 300 | 300 +(8 rows) + +ROLLBACK; +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY v1; + v1 | v2 +----+----- + 10 | 100 + 20 | 200 + 30 | 300 +(3 rows) + +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv ORDER BY v1; + v1 | v2 +------+----- + 10 | 100 + 11 | 100 + 1020 | 200 + 1020 | 222 +(4 rows) + +ROLLBACK; +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +NOTICE: created index "mv_ri_index" on materialized view "mv_ri" +SELECT * FROM mv_ri ORDER BY i1; + i1 | i2 +----+---- + 1 | 1 + 2 | 2 + 3 | 3 +(3 rows) + +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; + i1 | i2 +----+---- + 3 | 3 + 10 | 10 +(2 rows) + +ROLLBACK; +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | +(2 rows) + +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | 20 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i +--- +(0 rows) + +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; + i +--- + 1 + +(2 rows) + +ROLLBACK; +-- IMMV containing user defined type +BEGIN; +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: return type mytype is only a shell +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: argument type mytype is only a shell +LINE 1: CREATE FUNCTION mytype_out(mytype) + ^ +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +NOTICE: could not create an index on materialized view "mv_mytype" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + x +--- + 1 +(1 row) + +ROLLBACK; +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +ERROR: OUTER JOIN is not supported on incrementally maintainable materialized view +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +ERROR: CTE is not supported on incrementally maintainable materialized view +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +ERROR: ORDER BY clause is not supported on incrementally maintainable materialized view +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; +ERROR: HAVING clause is not supported on incrementally maintainable materialized view +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; +ERROR: mutable function is not supported on incrementally maintainable materialized view +HINT: functions must be marked IMMUTABLE +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; +ERROR: LIMIT/OFFSET clause is not supported on incrementally maintainable materialized view +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; +ERROR: DISTINCT is not supported on incrementally maintainable materialized view +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); +ERROR: TABLESAMPLE clause is not supported on incrementally maintainable materialized view +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; +ERROR: window functions are not supported on incrementally maintainable materialized view +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ERROR: inheritance parent is not supported on incrementally maintainable materialized view +ROLLBACK; +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; +ERROR: UNION/INTERSECT/EXCEPT statements are not supported on incrementally maintainable materialized view +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; +ERROR: empty target list is not supported on incrementally maintainable materialized view +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; +ERROR: FOR UPDATE/SHARE clause is not supported on incrementally maintainable materialized view +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; +ERROR: column name __ivm_count__ is not supported on incrementally maintainable materialized view +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; +ERROR: aggregate function is not supported on incrementally maintainable materialized view +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); +ERROR: VALUES is not supported on incrementally maintainable materialized view +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +NOTICE: role "regress_ivm_admin" does not exist, skipping +DROP USER IF EXISTS regress_ivm_user; +NOTICE: role "regress_ivm_user" does not exist, skipping +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +NOTICE: could not create an index on materialized view "ivm_rls" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user +(1 row) + +RESET SESSION AUTHORIZATION; +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user + 3 | baz | regress_ivm_user +(2 rows) + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +-- +(1 row) + +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+-------+------------------ + 2 | bar | regress_ivm_user + 3 | baz | regress_ivm_user + 6 | corge | regress_ivm_user +(3 rows) + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +NOTICE: could not create an index on materialized view "ivm_rls2" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +RESET SESSION AUTHORIZATION; +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +-- +(1 row) + +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + id | data | owner | num +----+-------+------------------+--------- + 2 | bar | regress_ivm_user | two + 3 | baz_2 | regress_ivm_user | three_2 + 6 | corge | regress_ivm_user | six +(3 rows) + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +NOTICE: could not create an index on materialized view "mv_update_same" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + i +--- + 2 +(1 row) + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +NOTICE: created index "mv_self_ref_index" on materialized view "mv_self_ref" +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; + a | b +----+---- + 11 | + 12 | 11 + 13 | 12 +(3 rows) + +ROLLBACK; +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; +NOTICE: created index "mv_idx3_index" on materialized view "mv_idx3" +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +NOTICE: could not create an index on materialized view "mv_idx4" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; +NOTICE: could not create an index on materialized view "mv_idx5" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); +NOTICE: could not create an index on materialized view "mv_idx6" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ERROR: data type json has no default operator class for access method "btree" +ROLLBACK; +-- cleanup +DROP TABLE rls_tbl CASCADE; +NOTICE: drop cascades to 2 other objects +DETAIL: drop cascades to materialized view ivm_rls +drop cascades to materialized view ivm_rls2 +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; +DROP TABLE mv_base_b CASCADE; +NOTICE: drop cascades to 3 other objects +DETAIL: drop cascades to materialized view mv_ivm_1 +drop cascades to view b_view +drop cascades to materialized view b_mview +DROP TABLE mv_base_a CASCADE; diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index 8fa0a6c47fb..7caca5f64fd 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -77,6 +77,7 @@ test: brin_bloom brin_multi # Another group of parallel tests # ---------- test: create_table_like alter_generic alter_operator misc async dbsize merge misc_functions nls sysviews tsrf tid tidscan tidrangescan collate.utf8 collate.icu.utf8 incremental_sort create_role without_overlaps generated_virtual +test: incremental_matview # collate.linux.utf8 and collate.icu.utf8 tests cannot be run in parallel with each other # psql depends on create_am diff --git a/src/test/regress/sql/incremental_matview.sql b/src/test/regress/sql/incremental_matview.sql new file mode 100644 index 00000000000..7313ad82f3e --- /dev/null +++ b/src/test/regress/sql/incremental_matview.sql @@ -0,0 +1,407 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); + +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +REFRESH MATERIALIZED VIEW mv_ivm_1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; + +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; +ROLLBACK; + +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- DISTINCT not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT * FROM mv_base_a; + +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; + + +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +ROLLBACK; + +-- result of materialized view have duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +ROLLBACK; + +-- aggregate not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; + +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +SELECT * FROM mv_self ORDER BY v1; +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; +SELECT * FROM mv_self ORDER BY v1; + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + +ROLLBACK; + +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +SELECT * FROM mv ORDER BY v1; +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; +SELECT * FROM mv ORDER BY v1; +ROLLBACK; + +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +SELECT * FROM mv_ri ORDER BY i1; +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; +ROLLBACK; + +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +-- IMMV containing user defined type +BEGIN; + +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); + +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; + +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); + +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); + +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + +ROLLBACK; + +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; + +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; + +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; + +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; + +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; + +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); + +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; + +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ROLLBACK; + +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; + +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; + +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; + +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; + +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; + +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); + +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +DROP USER IF EXISTS regress_ivm_user; +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; + +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); + +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; + +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; + +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; +RESET SESSION AUTHORIZATION; + +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +RESET SESSION AUTHORIZATION; + +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; +ROLLBACK; + +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); + +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; + +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; + +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); + +ROLLBACK; + +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ROLLBACK; + +-- cleanup + +DROP TABLE rls_tbl CASCADE; +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; + +DROP TABLE mv_base_b CASCADE; +DROP TABLE mv_base_a CASCADE; -- 2.43.0 --Multipart=_Fri__3_Jul_2026_19_11_16_+0900_CskxSIu_iGcDMEyM Content-Type: text/x-diff; name="v39-0006-Add-Incremental-View-Maintenance-support.patch" Content-Disposition: attachment; filename="v39-0006-Add-Incremental-View-Maintenance-support.patch" Content-Transfer-Encoding: 7bit ^ permalink raw reply [nested|flat] 78+ messages in thread
* [PATCH v38 10/11] Add regression tests for Incremental View Maintenance @ 2026-05-29 09:31 Yugo Nagata <[email protected]> 0 siblings, 0 replies; 78+ messages in thread From: Yugo Nagata @ 2026-05-29 09:31 UTC (permalink / raw) --- .../isolation/expected/ivm-create-insert.out | 285 +++++ .../isolation/expected/ivm-create-insert2.out | 305 +++++ .../isolation/expected/ivm-create-insert3.out | 305 +++++ .../isolation/expected/ivm-insert-insert.out | 497 ++++++++ .../isolation/expected/ivm-insert-insert2.out | 373 ++++++ .../isolation/expected/ivm-insert-insert3.out | 373 ++++++ .../isolation/expected/ivm-refresh-insert.out | 213 ++++ .../expected/ivm-refresh-insert2.out | 191 +++ .../expected/ivm-refresh-insert3.out | 191 +++ src/test/isolation/isolation_schedule | 9 + .../isolation/specs/ivm-create-insert.spec | 47 + .../isolation/specs/ivm-create-insert2.spec | 54 + .../isolation/specs/ivm-create-insert3.spec | 54 + .../isolation/specs/ivm-insert-insert.spec | 62 + .../isolation/specs/ivm-insert-insert2.spec | 62 + .../isolation/specs/ivm-insert-insert3.spec | 62 + .../isolation/specs/ivm-refresh-insert.spec | 46 + .../isolation/specs/ivm-refresh-insert2.spec | 46 + .../isolation/specs/ivm-refresh-insert3.spec | 46 + .../regress/expected/incremental_matview.out | 1100 +++++++++++++++++ src/test/regress/parallel_schedule | 1 + src/test/regress/sql/incremental_matview.sql | 580 +++++++++ 22 files changed, 4902 insertions(+) create mode 100644 src/test/isolation/expected/ivm-create-insert.out create mode 100644 src/test/isolation/expected/ivm-create-insert2.out create mode 100644 src/test/isolation/expected/ivm-create-insert3.out create mode 100644 src/test/isolation/expected/ivm-insert-insert.out create mode 100644 src/test/isolation/expected/ivm-insert-insert2.out create mode 100644 src/test/isolation/expected/ivm-insert-insert3.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert2.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert3.out create mode 100644 src/test/isolation/specs/ivm-create-insert.spec create mode 100644 src/test/isolation/specs/ivm-create-insert2.spec create mode 100644 src/test/isolation/specs/ivm-create-insert3.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert2.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert3.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert2.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert3.spec create mode 100644 src/test/regress/expected/incremental_matview.out create mode 100644 src/test/regress/sql/incremental_matview.sql diff --git a/src/test/isolation/expected/ivm-create-insert.out b/src/test/isolation/expected/ivm-create-insert.out new file mode 100644 index 00000000000..5da00043aba --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert.out @@ -0,0 +1,285 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-create-insert2.out b/src/test/isolation/expected/ivm-create-insert2.out new file mode 100644 index 00000000000..907d892c6d4 --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert2.out @@ -0,0 +1,305 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + diff --git a/src/test/isolation/expected/ivm-create-insert3.out b/src/test/isolation/expected/ivm-create-insert3.out new file mode 100644 index 00000000000..907d892c6d4 --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert3.out @@ -0,0 +1,305 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert.out b/src/test/isolation/expected/ivm-insert-insert.out new file mode 100644 index 00000000000..5ca4cfea677 --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert.out @@ -0,0 +1,497 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; <waiting ...> +step c1: COMMIT; +step update2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; <waiting ...> +step c1: COMMIT; +step update2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; <waiting ...> +step c2: COMMIT; +step update1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; <waiting ...> +step c2: COMMIT; +step update1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); <waiting ...> +step c1: COMMIT; +step insert2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); <waiting ...> +step c1: COMMIT; +step insert2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); <waiting ...> +step c2: COMMIT; +step insert1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); <waiting ...> +step c2: COMMIT; +step insert1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert2.out b/src/test/isolation/expected/ivm-insert-insert2.out new file mode 100644 index 00000000000..e1c66d4de5e --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert2.out @@ -0,0 +1,373 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert3.out b/src/test/isolation/expected/ivm-insert-insert3.out new file mode 100644 index 00000000000..e1c66d4de5e --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert3.out @@ -0,0 +1,373 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert.out b/src/test/isolation/expected/ivm-refresh-insert.out new file mode 100644 index 00000000000..a925938bf1c --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert.out @@ -0,0 +1,213 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert2.out b/src/test/isolation/expected/ivm-refresh-insert2.out new file mode 100644 index 00000000000..dc1b16ae34e --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert2.out @@ -0,0 +1,191 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert3.out b/src/test/isolation/expected/ivm-refresh-insert3.out new file mode 100644 index 00000000000..dc1b16ae34e --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert3.out @@ -0,0 +1,191 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/isolation_schedule b/src/test/isolation/isolation_schedule index b8ebe92553c..6b7e873b370 100644 --- a/src/test/isolation/isolation_schedule +++ b/src/test/isolation/isolation_schedule @@ -128,3 +128,12 @@ test: matview-write-skew test: lock-nowait test: for-portion-of test: ddl-dependency-locking +test: ivm-create-insert +test: ivm-create-insert2 +test: ivm-create-insert3 +test: ivm-insert-insert +test: ivm-insert-insert2 +test: ivm-insert-insert3 +test: ivm-refresh-insert +test: ivm-refresh-insert2 +test: ivm-refresh-insert3 diff --git a/src/test/isolation/specs/ivm-create-insert.spec b/src/test/isolation/specs/ivm-create-insert.spec new file mode 100644 index 00000000000..ccd6fd080a9 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert.spec @@ -0,0 +1,47 @@ +# Test interaction between concurrent transactions performing +# create and insert in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-create-insert2.spec b/src/test/isolation/specs/ivm-create-insert2.spec new file mode 100644 index 00000000000..02cec85ae07 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert2.spec @@ -0,0 +1,54 @@ +# Test interaction between concurrent transactions performing +# create and insert in REPEATABLE READ isolation level +# +# Note: +# In this isolation level, it is possible that create_immv could +# create an inconsistent view not including effects of a concurrent +# transaction. So, an warning message is raised to suggest using it +# in READ COMMITTED or executing refresh_immv to make sure to +# make the view contents consistent. + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-create-insert3.spec b/src/test/isolation/specs/ivm-create-insert3.spec new file mode 100644 index 00000000000..19ce03185a4 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert3.spec @@ -0,0 +1,54 @@ +# Test interaction between concurrent transactions performing +# create and insert in SERIALIZABLE isolation level +# +# Note: +# In this isolation level, it is possible that create_immv could +# create an inconsistent view not including effects of a concurrent +# transaction. So, an warning message is raised to suggest using it +# in READ COMMITTED or executing refresh_immv to make sure to +# make the view contents consistent. + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert.spec b/src/test/isolation/specs/ivm-insert-insert.spec new file mode 100644 index 00000000000..b8f794ca191 --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert2.spec b/src/test/isolation/specs/ivm-insert-insert2.spec new file mode 100644 index 00000000000..ed086d1ba1e --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert2.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in REPEATABLE READ isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert3.spec b/src/test/isolation/specs/ivm-insert-insert3.spec new file mode 100644 index 00000000000..b18bd121033 --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert3.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in SERIALIZABLE isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert.spec b/src/test/isolation/specs/ivm-refresh-insert.spec new file mode 100644 index 00000000000..d7181251962 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert2.spec b/src/test/isolation/specs/ivm-refresh-insert2.spec new file mode 100644 index 00000000000..f2d1d5013f2 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert2.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in REPEATABLE READ isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert3.spec b/src/test/isolation/specs/ivm-refresh-insert3.spec new file mode 100644 index 00000000000..0ec2b1d1de0 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert3.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in SERIALIZABLE isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/regress/expected/incremental_matview.out b/src/test/regress/expected/incremental_matview.out new file mode 100644 index 00000000000..f215aa88e48 --- /dev/null +++ b/src/test/regress/expected/incremental_matview.out @@ -0,0 +1,1100 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ERROR: materialized view "mv_ivm_1" has not been populated +HINT: Use the REFRESH MATERIALIZED VIEW command. +REFRESH MATERIALIZED VIEW mv_ivm_1; +NOTICE: could not create an index on materialized view "mv_ivm_1" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 17 +(1 row) + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 1 +(1 row) + +ROLLBACK; +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_rename_index" on materialized view "mv_ivm_rename" +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +ERROR: IVM column can not be renamed +DROP MATERIALIZED VIEW mv_ivm_rename; +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_unique_index" on materialized view "mv_ivm_unique" +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +ERROR: unique index creation on IVM columns is not supported +DROP MATERIALIZED VIEW mv_ivm_unique; +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +NOTICE: could not create an index on materialized view "mv_ivm_func" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +NOTICE: could not create an index on materialized view "mv_ivm_no_tbl" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_duplicate" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +NOTICE: created index "mv_ivm_distinct_index" on materialized view "mv_ivm_distinct" +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 20 + 30 + 40 + 50 +(6 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +ROLLBACK; +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 120 | 2 | 60.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+---------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 220 | 2 | 110.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 20 | 1 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 120 | 2 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; + sum | count +-----+------- +(0 rows) + +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; + i | sum | count +---+-----+------- +(0 rows) + +ROLLBACK; +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 150 | 5 | 30.0000000000000000 +(1 row) + +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 210 | 6 | 35.0000000000000000 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +NOTICE: created index "mv_ivm_avg_bug_index" on materialized view "mv_ivm_avg_bug" +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 3 | 3.3333333333333333 + 2 | 80 | 3 | 26.6666666666666667 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_min_max_index" on materialized view "mv_ivm_min_max" +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 10 + 2 | 20 | 20 + 3 | 30 | 30 + 4 | 40 | 40 + 5 | 50 | 50 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 12 + 2 | 20 | 22 + 3 | 30 | 32 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 11 | 12 + 2 | 20 | 22 + 3 | 30 | 31 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min_max" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 50 +(1 row) + +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 0 | 70 +(1 row) + +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 60 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + | +(1 row) + +ROLLBACK; +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min; + min +----- + 10 +(1 row) + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + min +----- + 20 +(1 row) + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; + min +----- + 30 +(1 row) + +ROLLBACK; +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | sum +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | b +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ERROR: too many column names were specified +ROLLBACK; +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +NOTICE: could not create an index on materialized view "mv_self" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +----+---- + 10 | 10 + 20 | 20 + 30 | 30 +(3 rows) + +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 30 | 30 + 40 | 40 + 200 | 200 +(3 rows) + +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 130 | 130 + 300 | 300 +(4 rows) + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 70 | 70 + 70 | 77 + 77 | 70 + 77 | 77 + 130 | 130 + 300 | 300 +(8 rows) + +ROLLBACK; +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY v1; + v1 | v2 +----+----- + 10 | 100 + 20 | 200 + 30 | 300 +(3 rows) + +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv ORDER BY v1; + v1 | v2 +------+----- + 10 | 100 + 11 | 100 + 1020 | 200 + 1020 | 222 +(4 rows) + +ROLLBACK; +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +NOTICE: created index "mv_ri_index" on materialized view "mv_ri" +SELECT * FROM mv_ri ORDER BY i1; + i1 | i2 +----+---- + 1 | 1 + 2 | 2 + 3 | 3 +(3 rows) + +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; + i1 | i2 +----+---- + 3 | 3 + 10 | 10 +(2 rows) + +ROLLBACK; +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | +(2 rows) + +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | 20 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i +--- +(0 rows) + +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; + i +--- + 1 + +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 30 + | 3 +(2 rows) + +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 300 + | 30 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 1 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 4 +(1 row) + +ROLLBACK; +-- IMMV containing user defined type +BEGIN; +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: return type mytype is only a shell +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: argument type mytype is only a shell +LINE 1: CREATE FUNCTION mytype_out(mytype) + ^ +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +NOTICE: could not create an index on materialized view "mv_mytype" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + x +--- + 1 +(1 row) + +ROLLBACK; +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +ERROR: OUTER JOIN is not supported on incrementally maintainable materialized view +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +ERROR: CTE is not supported on incrementally maintainable materialized view +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +ERROR: ORDER BY clause is not supported on incrementally maintainable materialized view +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; +ERROR: HAVING clause is not supported on incrementally maintainable materialized view +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; +ERROR: mutable function is not supported on incrementally maintainable materialized view +HINT: functions must be marked IMMUTABLE +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; +ERROR: LIMIT/OFFSET clause is not supported on incrementally maintainable materialized view +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; +ERROR: DISTINCT ON is not supported on incrementally maintainable materialized view +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); +ERROR: TABLESAMPLE clause is not supported on incrementally maintainable materialized view +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; +ERROR: window functions are not supported on incrementally maintainable materialized view +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +ERROR: aggregate function with FILTER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +ERROR: aggregate function with DISTINCT arguments is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +ERROR: aggregate function with ORDER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); +ERROR: GROUPING SETS, ROLLUP, or CUBE clauses is not supported on incrementally maintainable materialized view +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ERROR: inheritance parent is not supported on incrementally maintainable materialized view +ROLLBACK; +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; +ERROR: UNION/INTERSECT/EXCEPT statements are not supported on incrementally maintainable materialized view +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; +ERROR: empty target list is not supported on incrementally maintainable materialized view +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; +ERROR: FOR UPDATE/SHARE clause is not supported on incrementally maintainable materialized view +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; +ERROR: column name __ivm_count__ is not supported on incrementally maintainable materialized view +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; +ERROR: GROUP BY expression not appearing in select list is not supported on incrementally maintainable materialized view +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); +ERROR: VALUES is not supported on incrementally maintainable materialized view +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +NOTICE: role "regress_ivm_admin" does not exist, skipping +DROP USER IF EXISTS regress_ivm_user; +NOTICE: role "regress_ivm_user" does not exist, skipping +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +NOTICE: could not create an index on materialized view "ivm_rls" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user +(1 row) + +RESET SESSION AUTHORIZATION; +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user + 3 | baz | regress_ivm_user +(2 rows) + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +-- +(1 row) + +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+-------+------------------ + 2 | bar | regress_ivm_user + 3 | baz | regress_ivm_user + 6 | corge | regress_ivm_user +(3 rows) + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +NOTICE: could not create an index on materialized view "ivm_rls2" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +RESET SESSION AUTHORIZATION; +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +-- +(1 row) + +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + id | data | owner | num +----+-------+------------------+--------- + 2 | bar | regress_ivm_user | two + 3 | baz_2 | regress_ivm_user | three_2 + 6 | corge | regress_ivm_user | six +(3 rows) + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +NOTICE: could not create an index on materialized view "mv_update_same" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + i +--- + 2 +(1 row) + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +NOTICE: created index "mv_self_ref_index" on materialized view "mv_self_ref" +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; + a | b +----+---- + 11 | + 12 | 11 + 13 | 12 +(3 rows) + +ROLLBACK; +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; +NOTICE: created index "mv_idx1_index" on materialized view "mv_idx1" +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; +NOTICE: created index "mv_idx2_index" on materialized view "mv_idx2" +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; +NOTICE: created index "mv_idx3_index" on materialized view "mv_idx3" +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +NOTICE: could not create an index on materialized view "mv_idx4" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; +NOTICE: could not create an index on materialized view "mv_idx5" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); +NOTICE: could not create an index on materialized view "mv_idx6" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ERROR: data type json has no default operator class for access method "btree" +ROLLBACK; +-- cleanup +DROP TABLE rls_tbl CASCADE; +NOTICE: drop cascades to 2 other objects +DETAIL: drop cascades to materialized view ivm_rls +drop cascades to materialized view ivm_rls2 +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; +DROP TABLE mv_base_b CASCADE; +NOTICE: drop cascades to 3 other objects +DETAIL: drop cascades to materialized view mv_ivm_1 +drop cascades to view b_view +drop cascades to materialized view b_mview +DROP TABLE mv_base_a CASCADE; diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index 8fa0a6c47fb..7caca5f64fd 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -77,6 +77,7 @@ test: brin_bloom brin_multi # Another group of parallel tests # ---------- test: create_table_like alter_generic alter_operator misc async dbsize merge misc_functions nls sysviews tsrf tid tidscan tidrangescan collate.utf8 collate.icu.utf8 incremental_sort create_role without_overlaps generated_virtual +test: incremental_matview # collate.linux.utf8 and collate.icu.utf8 tests cannot be run in parallel with each other # psql depends on create_am diff --git a/src/test/regress/sql/incremental_matview.sql b/src/test/regress/sql/incremental_matview.sql new file mode 100644 index 00000000000..2d55c393d6f --- /dev/null +++ b/src/test/regress/sql/incremental_matview.sql @@ -0,0 +1,580 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); + +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +REFRESH MATERIALIZED VIEW mv_ivm_1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; + +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; +ROLLBACK; + +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +DROP MATERIALIZED VIEW mv_ivm_rename; + +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +DROP MATERIALIZED VIEW mv_ivm_unique; + +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; + + +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +ROLLBACK; + +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +ROLLBACK; + +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +ROLLBACK; + +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +ROLLBACK; + +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +ROLLBACK; + +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min; + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); + +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; +ROLLBACK; + +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +SELECT * FROM mv_self ORDER BY v1; +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; +SELECT * FROM mv_self ORDER BY v1; + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + +ROLLBACK; + +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +SELECT * FROM mv ORDER BY v1; +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; +SELECT * FROM mv ORDER BY v1; +ROLLBACK; + +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +SELECT * FROM mv_ri ORDER BY i1; +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; +ROLLBACK; + +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +-- IMMV containing user defined type +BEGIN; + +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); + +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; + +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); + +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); + +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + +ROLLBACK; + +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; + +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; + +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; + +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; + +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; + +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); + +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; + +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); + +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ROLLBACK; + +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; + +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; + +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; + +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; + +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; + +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; + +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); + +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +DROP USER IF EXISTS regress_ivm_user; +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; + +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); + +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; + +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; + +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; +RESET SESSION AUTHORIZATION; + +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +RESET SESSION AUTHORIZATION; + +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; +ROLLBACK; + +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); + +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; + +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; + +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; + +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; + +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); + +ROLLBACK; + +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ROLLBACK; + +-- cleanup + +DROP TABLE rls_tbl CASCADE; +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; + +DROP TABLE mv_base_b CASCADE; +DROP TABLE mv_base_a CASCADE; -- 2.43.0 --Multipart=_Wed__1_Jul_2026_00_04_01_+0900_OVSy2WWK_9aByzDJ Content-Type: text/x-diff; name="v38-0009-Add-support-for-min-max-aggregates-for-IVM.patch" Content-Disposition: attachment; filename="v38-0009-Add-support-for-min-max-aggregates-for-IVM.patch" Content-Transfer-Encoding: 7bit ^ permalink raw reply [nested|flat] 78+ messages in thread
* [PATCH v37 10/11] Add regression tests for Incremental View Maintenance @ 2026-05-29 09:31 Yugo Nagata <[email protected]> 0 siblings, 0 replies; 78+ messages in thread From: Yugo Nagata @ 2026-05-29 09:31 UTC (permalink / raw) --- src/test/isolation/isolation_schedule | 9 + .../regress/expected/incremental_matview.out | 1100 +++++++++++++++++ src/test/regress/parallel_schedule | 1 + src/test/regress/sql/incremental_matview.sql | 580 +++++++++ 4 files changed, 1690 insertions(+) create mode 100644 src/test/regress/expected/incremental_matview.out create mode 100644 src/test/regress/sql/incremental_matview.sql diff --git a/src/test/isolation/isolation_schedule b/src/test/isolation/isolation_schedule index 15c33fad4c5..111fd465207 100644 --- a/src/test/isolation/isolation_schedule +++ b/src/test/isolation/isolation_schedule @@ -127,3 +127,12 @@ test: matview-write-skew test: lock-nowait test: for-portion-of test: ddl-dependency-locking +test: ivm-create-insert +test: ivm-create-insert2 +test: ivm-create-insert3 +test: ivm-insert-insert +test: ivm-insert-insert2 +test: ivm-insert-insert3 +test: ivm-refresh-insert +test: ivm-refresh-insert2 +test: ivm-refresh-insert3 diff --git a/src/test/regress/expected/incremental_matview.out b/src/test/regress/expected/incremental_matview.out new file mode 100644 index 00000000000..f215aa88e48 --- /dev/null +++ b/src/test/regress/expected/incremental_matview.out @@ -0,0 +1,1100 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ERROR: materialized view "mv_ivm_1" has not been populated +HINT: Use the REFRESH MATERIALIZED VIEW command. +REFRESH MATERIALIZED VIEW mv_ivm_1; +NOTICE: could not create an index on materialized view "mv_ivm_1" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 17 +(1 row) + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 1 +(1 row) + +ROLLBACK; +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_rename_index" on materialized view "mv_ivm_rename" +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +ERROR: IVM column can not be renamed +DROP MATERIALIZED VIEW mv_ivm_rename; +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_unique_index" on materialized view "mv_ivm_unique" +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +ERROR: unique index creation on IVM columns is not supported +DROP MATERIALIZED VIEW mv_ivm_unique; +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +NOTICE: could not create an index on materialized view "mv_ivm_func" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +NOTICE: could not create an index on materialized view "mv_ivm_no_tbl" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_duplicate" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +NOTICE: created index "mv_ivm_distinct_index" on materialized view "mv_ivm_distinct" +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 20 + 30 + 40 + 50 +(6 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +ROLLBACK; +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 120 | 2 | 60.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+---------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 220 | 2 | 110.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 20 | 1 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 120 | 2 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; + sum | count +-----+------- +(0 rows) + +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; + i | sum | count +---+-----+------- +(0 rows) + +ROLLBACK; +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 150 | 5 | 30.0000000000000000 +(1 row) + +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 210 | 6 | 35.0000000000000000 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +NOTICE: created index "mv_ivm_avg_bug_index" on materialized view "mv_ivm_avg_bug" +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 3 | 3.3333333333333333 + 2 | 80 | 3 | 26.6666666666666667 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_min_max_index" on materialized view "mv_ivm_min_max" +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 10 + 2 | 20 | 20 + 3 | 30 | 30 + 4 | 40 | 40 + 5 | 50 | 50 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 12 + 2 | 20 | 22 + 3 | 30 | 32 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 11 | 12 + 2 | 20 | 22 + 3 | 30 | 31 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min_max" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 50 +(1 row) + +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 0 | 70 +(1 row) + +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 60 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + | +(1 row) + +ROLLBACK; +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min; + min +----- + 10 +(1 row) + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + min +----- + 20 +(1 row) + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; + min +----- + 30 +(1 row) + +ROLLBACK; +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | sum +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | b +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ERROR: too many column names were specified +ROLLBACK; +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +NOTICE: could not create an index on materialized view "mv_self" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +----+---- + 10 | 10 + 20 | 20 + 30 | 30 +(3 rows) + +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 30 | 30 + 40 | 40 + 200 | 200 +(3 rows) + +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 130 | 130 + 300 | 300 +(4 rows) + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 70 | 70 + 70 | 77 + 77 | 70 + 77 | 77 + 130 | 130 + 300 | 300 +(8 rows) + +ROLLBACK; +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY v1; + v1 | v2 +----+----- + 10 | 100 + 20 | 200 + 30 | 300 +(3 rows) + +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv ORDER BY v1; + v1 | v2 +------+----- + 10 | 100 + 11 | 100 + 1020 | 200 + 1020 | 222 +(4 rows) + +ROLLBACK; +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +NOTICE: created index "mv_ri_index" on materialized view "mv_ri" +SELECT * FROM mv_ri ORDER BY i1; + i1 | i2 +----+---- + 1 | 1 + 2 | 2 + 3 | 3 +(3 rows) + +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; + i1 | i2 +----+---- + 3 | 3 + 10 | 10 +(2 rows) + +ROLLBACK; +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | +(2 rows) + +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | 20 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i +--- +(0 rows) + +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; + i +--- + 1 + +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 30 + | 3 +(2 rows) + +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 300 + | 30 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 1 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 4 +(1 row) + +ROLLBACK; +-- IMMV containing user defined type +BEGIN; +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: return type mytype is only a shell +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: argument type mytype is only a shell +LINE 1: CREATE FUNCTION mytype_out(mytype) + ^ +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +NOTICE: could not create an index on materialized view "mv_mytype" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + x +--- + 1 +(1 row) + +ROLLBACK; +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +ERROR: OUTER JOIN is not supported on incrementally maintainable materialized view +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +ERROR: CTE is not supported on incrementally maintainable materialized view +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +ERROR: ORDER BY clause is not supported on incrementally maintainable materialized view +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; +ERROR: HAVING clause is not supported on incrementally maintainable materialized view +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; +ERROR: mutable function is not supported on incrementally maintainable materialized view +HINT: functions must be marked IMMUTABLE +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; +ERROR: LIMIT/OFFSET clause is not supported on incrementally maintainable materialized view +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; +ERROR: DISTINCT ON is not supported on incrementally maintainable materialized view +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); +ERROR: TABLESAMPLE clause is not supported on incrementally maintainable materialized view +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; +ERROR: window functions are not supported on incrementally maintainable materialized view +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +ERROR: aggregate function with FILTER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +ERROR: aggregate function with DISTINCT arguments is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +ERROR: aggregate function with ORDER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); +ERROR: GROUPING SETS, ROLLUP, or CUBE clauses is not supported on incrementally maintainable materialized view +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ERROR: inheritance parent is not supported on incrementally maintainable materialized view +ROLLBACK; +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; +ERROR: UNION/INTERSECT/EXCEPT statements are not supported on incrementally maintainable materialized view +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; +ERROR: empty target list is not supported on incrementally maintainable materialized view +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; +ERROR: FOR UPDATE/SHARE clause is not supported on incrementally maintainable materialized view +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; +ERROR: column name __ivm_count__ is not supported on incrementally maintainable materialized view +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; +ERROR: GROUP BY expression not appearing in select list is not supported on incrementally maintainable materialized view +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); +ERROR: VALUES is not supported on incrementally maintainable materialized view +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +NOTICE: role "regress_ivm_admin" does not exist, skipping +DROP USER IF EXISTS regress_ivm_user; +NOTICE: role "regress_ivm_user" does not exist, skipping +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +NOTICE: could not create an index on materialized view "ivm_rls" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user +(1 row) + +RESET SESSION AUTHORIZATION; +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user + 3 | baz | regress_ivm_user +(2 rows) + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +-- +(1 row) + +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+-------+------------------ + 2 | bar | regress_ivm_user + 3 | baz | regress_ivm_user + 6 | corge | regress_ivm_user +(3 rows) + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +NOTICE: could not create an index on materialized view "ivm_rls2" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +RESET SESSION AUTHORIZATION; +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +-- +(1 row) + +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + id | data | owner | num +----+-------+------------------+--------- + 2 | bar | regress_ivm_user | two + 3 | baz_2 | regress_ivm_user | three_2 + 6 | corge | regress_ivm_user | six +(3 rows) + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +NOTICE: could not create an index on materialized view "mv_update_same" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + i +--- + 2 +(1 row) + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +NOTICE: created index "mv_self_ref_index" on materialized view "mv_self_ref" +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; + a | b +----+---- + 11 | + 12 | 11 + 13 | 12 +(3 rows) + +ROLLBACK; +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; +NOTICE: created index "mv_idx1_index" on materialized view "mv_idx1" +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; +NOTICE: created index "mv_idx2_index" on materialized view "mv_idx2" +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; +NOTICE: created index "mv_idx3_index" on materialized view "mv_idx3" +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +NOTICE: could not create an index on materialized view "mv_idx4" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; +NOTICE: could not create an index on materialized view "mv_idx5" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); +NOTICE: could not create an index on materialized view "mv_idx6" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ERROR: data type json has no default operator class for access method "btree" +ROLLBACK; +-- cleanup +DROP TABLE rls_tbl CASCADE; +NOTICE: drop cascades to 2 other objects +DETAIL: drop cascades to materialized view ivm_rls +drop cascades to materialized view ivm_rls2 +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; +DROP TABLE mv_base_b CASCADE; +NOTICE: drop cascades to 3 other objects +DETAIL: drop cascades to materialized view mv_ivm_1 +drop cascades to view b_view +drop cascades to materialized view b_mview +DROP TABLE mv_base_a CASCADE; diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index 8fa0a6c47fb..7caca5f64fd 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -77,6 +77,7 @@ test: brin_bloom brin_multi # Another group of parallel tests # ---------- test: create_table_like alter_generic alter_operator misc async dbsize merge misc_functions nls sysviews tsrf tid tidscan tidrangescan collate.utf8 collate.icu.utf8 incremental_sort create_role without_overlaps generated_virtual +test: incremental_matview # collate.linux.utf8 and collate.icu.utf8 tests cannot be run in parallel with each other # psql depends on create_am diff --git a/src/test/regress/sql/incremental_matview.sql b/src/test/regress/sql/incremental_matview.sql new file mode 100644 index 00000000000..2d55c393d6f --- /dev/null +++ b/src/test/regress/sql/incremental_matview.sql @@ -0,0 +1,580 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); + +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +REFRESH MATERIALIZED VIEW mv_ivm_1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; + +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; +ROLLBACK; + +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +DROP MATERIALIZED VIEW mv_ivm_rename; + +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +DROP MATERIALIZED VIEW mv_ivm_unique; + +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; + + +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +ROLLBACK; + +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +ROLLBACK; + +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +ROLLBACK; + +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +ROLLBACK; + +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +ROLLBACK; + +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min; + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); + +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; +ROLLBACK; + +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +SELECT * FROM mv_self ORDER BY v1; +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; +SELECT * FROM mv_self ORDER BY v1; + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + +ROLLBACK; + +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +SELECT * FROM mv ORDER BY v1; +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; +SELECT * FROM mv ORDER BY v1; +ROLLBACK; + +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +SELECT * FROM mv_ri ORDER BY i1; +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; +ROLLBACK; + +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +-- IMMV containing user defined type +BEGIN; + +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); + +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; + +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); + +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); + +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + +ROLLBACK; + +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; + +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; + +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; + +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; + +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; + +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); + +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; + +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); + +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ROLLBACK; + +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; + +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; + +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; + +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; + +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; + +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; + +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); + +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +DROP USER IF EXISTS regress_ivm_user; +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; + +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); + +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; + +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; + +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; +RESET SESSION AUTHORIZATION; + +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +RESET SESSION AUTHORIZATION; + +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; +ROLLBACK; + +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); + +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; + +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; + +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; + +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; + +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); + +ROLLBACK; + +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ROLLBACK; + +-- cleanup + +DROP TABLE rls_tbl CASCADE; +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; + +DROP TABLE mv_base_b CASCADE; +DROP TABLE mv_base_a CASCADE; -- 2.43.0 --Multipart=_Fri__29_May_2026_23_14_17_+0900_Te0o73X2VqYK57Gd Content-Type: text/x-diff; name="v37-0009-Add-support-for-min-max-aggregates-for-IVM.patch" Content-Disposition: attachment; filename="v37-0009-Add-support-for-min-max-aggregates-for-IVM.patch" Content-Transfer-Encoding: 7bit ^ permalink raw reply [nested|flat] 78+ messages in thread
* [PATCH v37 10/11] Add regression tests for Incremental View Maintenance @ 2026-05-29 09:31 Yugo Nagata <[email protected]> 0 siblings, 0 replies; 78+ messages in thread From: Yugo Nagata @ 2026-05-29 09:31 UTC (permalink / raw) --- src/test/isolation/isolation_schedule | 9 + .../regress/expected/incremental_matview.out | 1100 +++++++++++++++++ src/test/regress/parallel_schedule | 1 + src/test/regress/sql/incremental_matview.sql | 580 +++++++++ 4 files changed, 1690 insertions(+) create mode 100644 src/test/regress/expected/incremental_matview.out create mode 100644 src/test/regress/sql/incremental_matview.sql diff --git a/src/test/isolation/isolation_schedule b/src/test/isolation/isolation_schedule index 15c33fad4c5..111fd465207 100644 --- a/src/test/isolation/isolation_schedule +++ b/src/test/isolation/isolation_schedule @@ -127,3 +127,12 @@ test: matview-write-skew test: lock-nowait test: for-portion-of test: ddl-dependency-locking +test: ivm-create-insert +test: ivm-create-insert2 +test: ivm-create-insert3 +test: ivm-insert-insert +test: ivm-insert-insert2 +test: ivm-insert-insert3 +test: ivm-refresh-insert +test: ivm-refresh-insert2 +test: ivm-refresh-insert3 diff --git a/src/test/regress/expected/incremental_matview.out b/src/test/regress/expected/incremental_matview.out new file mode 100644 index 00000000000..f215aa88e48 --- /dev/null +++ b/src/test/regress/expected/incremental_matview.out @@ -0,0 +1,1100 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ERROR: materialized view "mv_ivm_1" has not been populated +HINT: Use the REFRESH MATERIALIZED VIEW command. +REFRESH MATERIALIZED VIEW mv_ivm_1; +NOTICE: could not create an index on materialized view "mv_ivm_1" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 17 +(1 row) + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 1 +(1 row) + +ROLLBACK; +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_rename_index" on materialized view "mv_ivm_rename" +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +ERROR: IVM column can not be renamed +DROP MATERIALIZED VIEW mv_ivm_rename; +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_unique_index" on materialized view "mv_ivm_unique" +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +ERROR: unique index creation on IVM columns is not supported +DROP MATERIALIZED VIEW mv_ivm_unique; +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +NOTICE: could not create an index on materialized view "mv_ivm_func" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +NOTICE: could not create an index on materialized view "mv_ivm_no_tbl" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_duplicate" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +NOTICE: created index "mv_ivm_distinct_index" on materialized view "mv_ivm_distinct" +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 20 + 30 + 40 + 50 +(6 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +ROLLBACK; +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 120 | 2 | 60.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+---------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 220 | 2 | 110.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 20 | 1 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 120 | 2 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; + sum | count +-----+------- +(0 rows) + +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; + i | sum | count +---+-----+------- +(0 rows) + +ROLLBACK; +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 150 | 5 | 30.0000000000000000 +(1 row) + +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 210 | 6 | 35.0000000000000000 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +NOTICE: created index "mv_ivm_avg_bug_index" on materialized view "mv_ivm_avg_bug" +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 3 | 3.3333333333333333 + 2 | 80 | 3 | 26.6666666666666667 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_min_max_index" on materialized view "mv_ivm_min_max" +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 10 + 2 | 20 | 20 + 3 | 30 | 30 + 4 | 40 | 40 + 5 | 50 | 50 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 12 + 2 | 20 | 22 + 3 | 30 | 32 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 11 | 12 + 2 | 20 | 22 + 3 | 30 | 31 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min_max" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 50 +(1 row) + +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 0 | 70 +(1 row) + +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 60 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + | +(1 row) + +ROLLBACK; +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min; + min +----- + 10 +(1 row) + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + min +----- + 20 +(1 row) + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; + min +----- + 30 +(1 row) + +ROLLBACK; +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | sum +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | b +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ERROR: too many column names were specified +ROLLBACK; +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +NOTICE: could not create an index on materialized view "mv_self" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +----+---- + 10 | 10 + 20 | 20 + 30 | 30 +(3 rows) + +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 30 | 30 + 40 | 40 + 200 | 200 +(3 rows) + +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 130 | 130 + 300 | 300 +(4 rows) + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 70 | 70 + 70 | 77 + 77 | 70 + 77 | 77 + 130 | 130 + 300 | 300 +(8 rows) + +ROLLBACK; +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY v1; + v1 | v2 +----+----- + 10 | 100 + 20 | 200 + 30 | 300 +(3 rows) + +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv ORDER BY v1; + v1 | v2 +------+----- + 10 | 100 + 11 | 100 + 1020 | 200 + 1020 | 222 +(4 rows) + +ROLLBACK; +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +NOTICE: created index "mv_ri_index" on materialized view "mv_ri" +SELECT * FROM mv_ri ORDER BY i1; + i1 | i2 +----+---- + 1 | 1 + 2 | 2 + 3 | 3 +(3 rows) + +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; + i1 | i2 +----+---- + 3 | 3 + 10 | 10 +(2 rows) + +ROLLBACK; +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | +(2 rows) + +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | 20 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i +--- +(0 rows) + +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; + i +--- + 1 + +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 30 + | 3 +(2 rows) + +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 300 + | 30 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 1 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 4 +(1 row) + +ROLLBACK; +-- IMMV containing user defined type +BEGIN; +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: return type mytype is only a shell +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: argument type mytype is only a shell +LINE 1: CREATE FUNCTION mytype_out(mytype) + ^ +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +NOTICE: could not create an index on materialized view "mv_mytype" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + x +--- + 1 +(1 row) + +ROLLBACK; +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +ERROR: OUTER JOIN is not supported on incrementally maintainable materialized view +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +ERROR: CTE is not supported on incrementally maintainable materialized view +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +ERROR: ORDER BY clause is not supported on incrementally maintainable materialized view +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; +ERROR: HAVING clause is not supported on incrementally maintainable materialized view +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; +ERROR: mutable function is not supported on incrementally maintainable materialized view +HINT: functions must be marked IMMUTABLE +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; +ERROR: LIMIT/OFFSET clause is not supported on incrementally maintainable materialized view +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; +ERROR: DISTINCT ON is not supported on incrementally maintainable materialized view +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); +ERROR: TABLESAMPLE clause is not supported on incrementally maintainable materialized view +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; +ERROR: window functions are not supported on incrementally maintainable materialized view +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +ERROR: aggregate function with FILTER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +ERROR: aggregate function with DISTINCT arguments is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +ERROR: aggregate function with ORDER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); +ERROR: GROUPING SETS, ROLLUP, or CUBE clauses is not supported on incrementally maintainable materialized view +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ERROR: inheritance parent is not supported on incrementally maintainable materialized view +ROLLBACK; +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; +ERROR: UNION/INTERSECT/EXCEPT statements are not supported on incrementally maintainable materialized view +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; +ERROR: empty target list is not supported on incrementally maintainable materialized view +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; +ERROR: FOR UPDATE/SHARE clause is not supported on incrementally maintainable materialized view +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; +ERROR: column name __ivm_count__ is not supported on incrementally maintainable materialized view +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; +ERROR: GROUP BY expression not appearing in select list is not supported on incrementally maintainable materialized view +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); +ERROR: VALUES is not supported on incrementally maintainable materialized view +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +NOTICE: role "regress_ivm_admin" does not exist, skipping +DROP USER IF EXISTS regress_ivm_user; +NOTICE: role "regress_ivm_user" does not exist, skipping +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +NOTICE: could not create an index on materialized view "ivm_rls" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user +(1 row) + +RESET SESSION AUTHORIZATION; +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user + 3 | baz | regress_ivm_user +(2 rows) + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +-- +(1 row) + +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+-------+------------------ + 2 | bar | regress_ivm_user + 3 | baz | regress_ivm_user + 6 | corge | regress_ivm_user +(3 rows) + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +NOTICE: could not create an index on materialized view "ivm_rls2" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +RESET SESSION AUTHORIZATION; +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +-- +(1 row) + +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + id | data | owner | num +----+-------+------------------+--------- + 2 | bar | regress_ivm_user | two + 3 | baz_2 | regress_ivm_user | three_2 + 6 | corge | regress_ivm_user | six +(3 rows) + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +NOTICE: could not create an index on materialized view "mv_update_same" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + i +--- + 2 +(1 row) + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +NOTICE: created index "mv_self_ref_index" on materialized view "mv_self_ref" +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; + a | b +----+---- + 11 | + 12 | 11 + 13 | 12 +(3 rows) + +ROLLBACK; +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; +NOTICE: created index "mv_idx1_index" on materialized view "mv_idx1" +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; +NOTICE: created index "mv_idx2_index" on materialized view "mv_idx2" +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; +NOTICE: created index "mv_idx3_index" on materialized view "mv_idx3" +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +NOTICE: could not create an index on materialized view "mv_idx4" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; +NOTICE: could not create an index on materialized view "mv_idx5" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); +NOTICE: could not create an index on materialized view "mv_idx6" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ERROR: data type json has no default operator class for access method "btree" +ROLLBACK; +-- cleanup +DROP TABLE rls_tbl CASCADE; +NOTICE: drop cascades to 2 other objects +DETAIL: drop cascades to materialized view ivm_rls +drop cascades to materialized view ivm_rls2 +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; +DROP TABLE mv_base_b CASCADE; +NOTICE: drop cascades to 3 other objects +DETAIL: drop cascades to materialized view mv_ivm_1 +drop cascades to view b_view +drop cascades to materialized view b_mview +DROP TABLE mv_base_a CASCADE; diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index 8fa0a6c47fb..7caca5f64fd 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -77,6 +77,7 @@ test: brin_bloom brin_multi # Another group of parallel tests # ---------- test: create_table_like alter_generic alter_operator misc async dbsize merge misc_functions nls sysviews tsrf tid tidscan tidrangescan collate.utf8 collate.icu.utf8 incremental_sort create_role without_overlaps generated_virtual +test: incremental_matview # collate.linux.utf8 and collate.icu.utf8 tests cannot be run in parallel with each other # psql depends on create_am diff --git a/src/test/regress/sql/incremental_matview.sql b/src/test/regress/sql/incremental_matview.sql new file mode 100644 index 00000000000..2d55c393d6f --- /dev/null +++ b/src/test/regress/sql/incremental_matview.sql @@ -0,0 +1,580 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); + +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +REFRESH MATERIALIZED VIEW mv_ivm_1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; + +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; +ROLLBACK; + +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +DROP MATERIALIZED VIEW mv_ivm_rename; + +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +DROP MATERIALIZED VIEW mv_ivm_unique; + +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; + + +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +ROLLBACK; + +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +ROLLBACK; + +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +ROLLBACK; + +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +ROLLBACK; + +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +ROLLBACK; + +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min; + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); + +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; +ROLLBACK; + +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +SELECT * FROM mv_self ORDER BY v1; +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; +SELECT * FROM mv_self ORDER BY v1; + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + +ROLLBACK; + +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +SELECT * FROM mv ORDER BY v1; +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; +SELECT * FROM mv ORDER BY v1; +ROLLBACK; + +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +SELECT * FROM mv_ri ORDER BY i1; +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; +ROLLBACK; + +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +-- IMMV containing user defined type +BEGIN; + +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); + +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; + +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); + +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); + +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + +ROLLBACK; + +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; + +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; + +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; + +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; + +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; + +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); + +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; + +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); + +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ROLLBACK; + +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; + +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; + +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; + +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; + +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; + +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; + +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); + +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +DROP USER IF EXISTS regress_ivm_user; +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; + +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); + +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; + +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; + +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; +RESET SESSION AUTHORIZATION; + +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +RESET SESSION AUTHORIZATION; + +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; +ROLLBACK; + +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); + +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; + +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; + +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; + +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; + +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); + +ROLLBACK; + +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ROLLBACK; + +-- cleanup + +DROP TABLE rls_tbl CASCADE; +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; + +DROP TABLE mv_base_b CASCADE; +DROP TABLE mv_base_a CASCADE; -- 2.43.0 --Multipart=_Fri__29_May_2026_23_14_17_+0900_Te0o73X2VqYK57Gd Content-Type: text/x-diff; name="v37-0009-Add-support-for-min-max-aggregates-for-IVM.patch" Content-Disposition: attachment; filename="v37-0009-Add-support-for-min-max-aggregates-for-IVM.patch" Content-Transfer-Encoding: 7bit ^ permalink raw reply [nested|flat] 78+ messages in thread
* [PATCH v39 7/8] Add regression tests for Incremental View Maintenance @ 2026-05-29 09:31 Yugo Nagata <[email protected]> 0 siblings, 0 replies; 78+ messages in thread From: Yugo Nagata @ 2026-05-29 09:31 UTC (permalink / raw) --- .../isolation/expected/ivm-create-insert.out | 285 ++++++++ .../isolation/expected/ivm-create-insert2.out | 305 ++++++++ .../isolation/expected/ivm-create-insert3.out | 305 ++++++++ .../isolation/expected/ivm-insert-insert.out | 497 +++++++++++++ .../isolation/expected/ivm-insert-insert2.out | 373 ++++++++++ .../isolation/expected/ivm-insert-insert3.out | 373 ++++++++++ .../isolation/expected/ivm-refresh-insert.out | 213 ++++++ .../expected/ivm-refresh-insert2.out | 191 +++++ .../expected/ivm-refresh-insert3.out | 191 +++++ src/test/isolation/isolation_schedule | 9 + .../isolation/specs/ivm-create-insert.spec | 47 ++ .../isolation/specs/ivm-create-insert2.spec | 54 ++ .../isolation/specs/ivm-create-insert3.spec | 54 ++ .../isolation/specs/ivm-insert-insert.spec | 62 ++ .../isolation/specs/ivm-insert-insert2.spec | 62 ++ .../isolation/specs/ivm-insert-insert3.spec | 62 ++ .../isolation/specs/ivm-refresh-insert.spec | 46 ++ .../isolation/specs/ivm-refresh-insert2.spec | 46 ++ .../isolation/specs/ivm-refresh-insert3.spec | 46 ++ .../regress/expected/incremental_matview.out | 667 ++++++++++++++++++ src/test/regress/parallel_schedule | 1 + src/test/regress/sql/incremental_matview.sql | 407 +++++++++++ 22 files changed, 4296 insertions(+) create mode 100644 src/test/isolation/expected/ivm-create-insert.out create mode 100644 src/test/isolation/expected/ivm-create-insert2.out create mode 100644 src/test/isolation/expected/ivm-create-insert3.out create mode 100644 src/test/isolation/expected/ivm-insert-insert.out create mode 100644 src/test/isolation/expected/ivm-insert-insert2.out create mode 100644 src/test/isolation/expected/ivm-insert-insert3.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert2.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert3.out create mode 100644 src/test/isolation/specs/ivm-create-insert.spec create mode 100644 src/test/isolation/specs/ivm-create-insert2.spec create mode 100644 src/test/isolation/specs/ivm-create-insert3.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert2.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert3.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert2.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert3.spec create mode 100644 src/test/regress/expected/incremental_matview.out create mode 100644 src/test/regress/sql/incremental_matview.sql diff --git a/src/test/isolation/expected/ivm-create-insert.out b/src/test/isolation/expected/ivm-create-insert.out new file mode 100644 index 00000000000..5da00043aba --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert.out @@ -0,0 +1,285 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-create-insert2.out b/src/test/isolation/expected/ivm-create-insert2.out new file mode 100644 index 00000000000..907d892c6d4 --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert2.out @@ -0,0 +1,305 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + diff --git a/src/test/isolation/expected/ivm-create-insert3.out b/src/test/isolation/expected/ivm-create-insert3.out new file mode 100644 index 00000000000..907d892c6d4 --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert3.out @@ -0,0 +1,305 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert.out b/src/test/isolation/expected/ivm-insert-insert.out new file mode 100644 index 00000000000..5ca4cfea677 --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert.out @@ -0,0 +1,497 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; <waiting ...> +step c1: COMMIT; +step update2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; <waiting ...> +step c1: COMMIT; +step update2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; <waiting ...> +step c2: COMMIT; +step update1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; <waiting ...> +step c2: COMMIT; +step update1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); <waiting ...> +step c1: COMMIT; +step insert2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); <waiting ...> +step c1: COMMIT; +step insert2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); <waiting ...> +step c2: COMMIT; +step insert1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); <waiting ...> +step c2: COMMIT; +step insert1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert2.out b/src/test/isolation/expected/ivm-insert-insert2.out new file mode 100644 index 00000000000..e1c66d4de5e --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert2.out @@ -0,0 +1,373 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert3.out b/src/test/isolation/expected/ivm-insert-insert3.out new file mode 100644 index 00000000000..e1c66d4de5e --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert3.out @@ -0,0 +1,373 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert.out b/src/test/isolation/expected/ivm-refresh-insert.out new file mode 100644 index 00000000000..a925938bf1c --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert.out @@ -0,0 +1,213 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert2.out b/src/test/isolation/expected/ivm-refresh-insert2.out new file mode 100644 index 00000000000..dc1b16ae34e --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert2.out @@ -0,0 +1,191 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert3.out b/src/test/isolation/expected/ivm-refresh-insert3.out new file mode 100644 index 00000000000..dc1b16ae34e --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert3.out @@ -0,0 +1,191 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/isolation_schedule b/src/test/isolation/isolation_schedule index b8ebe92553c..6b7e873b370 100644 --- a/src/test/isolation/isolation_schedule +++ b/src/test/isolation/isolation_schedule @@ -128,3 +128,12 @@ test: matview-write-skew test: lock-nowait test: for-portion-of test: ddl-dependency-locking +test: ivm-create-insert +test: ivm-create-insert2 +test: ivm-create-insert3 +test: ivm-insert-insert +test: ivm-insert-insert2 +test: ivm-insert-insert3 +test: ivm-refresh-insert +test: ivm-refresh-insert2 +test: ivm-refresh-insert3 diff --git a/src/test/isolation/specs/ivm-create-insert.spec b/src/test/isolation/specs/ivm-create-insert.spec new file mode 100644 index 00000000000..ccd6fd080a9 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert.spec @@ -0,0 +1,47 @@ +# Test interaction between concurrent transactions performing +# create and insert in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-create-insert2.spec b/src/test/isolation/specs/ivm-create-insert2.spec new file mode 100644 index 00000000000..02cec85ae07 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert2.spec @@ -0,0 +1,54 @@ +# Test interaction between concurrent transactions performing +# create and insert in REPEATABLE READ isolation level +# +# Note: +# In this isolation level, it is possible that create_immv could +# create an inconsistent view not including effects of a concurrent +# transaction. So, an warning message is raised to suggest using it +# in READ COMMITTED or executing refresh_immv to make sure to +# make the view contents consistent. + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-create-insert3.spec b/src/test/isolation/specs/ivm-create-insert3.spec new file mode 100644 index 00000000000..19ce03185a4 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert3.spec @@ -0,0 +1,54 @@ +# Test interaction between concurrent transactions performing +# create and insert in SERIALIZABLE isolation level +# +# Note: +# In this isolation level, it is possible that create_immv could +# create an inconsistent view not including effects of a concurrent +# transaction. So, an warning message is raised to suggest using it +# in READ COMMITTED or executing refresh_immv to make sure to +# make the view contents consistent. + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert.spec b/src/test/isolation/specs/ivm-insert-insert.spec new file mode 100644 index 00000000000..b8f794ca191 --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert2.spec b/src/test/isolation/specs/ivm-insert-insert2.spec new file mode 100644 index 00000000000..ed086d1ba1e --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert2.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in REPEATABLE READ isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert3.spec b/src/test/isolation/specs/ivm-insert-insert3.spec new file mode 100644 index 00000000000..b18bd121033 --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert3.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in SERIALIZABLE isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert.spec b/src/test/isolation/specs/ivm-refresh-insert.spec new file mode 100644 index 00000000000..d7181251962 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert2.spec b/src/test/isolation/specs/ivm-refresh-insert2.spec new file mode 100644 index 00000000000..f2d1d5013f2 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert2.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in REPEATABLE READ isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert3.spec b/src/test/isolation/specs/ivm-refresh-insert3.spec new file mode 100644 index 00000000000..0ec2b1d1de0 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert3.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in SERIALIZABLE isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/regress/expected/incremental_matview.out b/src/test/regress/expected/incremental_matview.out new file mode 100644 index 00000000000..c7fd19fdca3 --- /dev/null +++ b/src/test/regress/expected/incremental_matview.out @@ -0,0 +1,667 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ERROR: materialized view "mv_ivm_1" has not been populated +HINT: Use the REFRESH MATERIALIZED VIEW command. +REFRESH MATERIALIZED VIEW mv_ivm_1; +NOTICE: could not create an index on materialized view "mv_ivm_1" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 17 +(1 row) + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 1 +(1 row) + +ROLLBACK; +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- DISTINCT not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT * FROM mv_base_a; +ERROR: DISTINCT is not supported on incrementally maintainable materialized view +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +NOTICE: could not create an index on materialized view "mv_ivm_func" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +NOTICE: could not create an index on materialized view "mv_ivm_no_tbl" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- result of materialized view have duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_duplicate" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 20 + 30 + 40 + 50 +(6 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +ROLLBACK; +-- aggregate not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +ERROR: aggregate function is not supported on incrementally maintainable materialized view +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +NOTICE: could not create an index on materialized view "mv_self" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +----+---- + 10 | 10 + 20 | 20 + 30 | 30 +(3 rows) + +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 30 | 30 + 40 | 40 + 200 | 200 +(3 rows) + +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 130 | 130 + 300 | 300 +(4 rows) + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 70 | 70 + 70 | 77 + 77 | 70 + 77 | 77 + 130 | 130 + 300 | 300 +(8 rows) + +ROLLBACK; +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY v1; + v1 | v2 +----+----- + 10 | 100 + 20 | 200 + 30 | 300 +(3 rows) + +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv ORDER BY v1; + v1 | v2 +------+----- + 10 | 100 + 11 | 100 + 1020 | 200 + 1020 | 222 +(4 rows) + +ROLLBACK; +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +NOTICE: created index "mv_ri_index" on materialized view "mv_ri" +SELECT * FROM mv_ri ORDER BY i1; + i1 | i2 +----+---- + 1 | 1 + 2 | 2 + 3 | 3 +(3 rows) + +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; + i1 | i2 +----+---- + 3 | 3 + 10 | 10 +(2 rows) + +ROLLBACK; +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | +(2 rows) + +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | 20 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i +--- +(0 rows) + +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; + i +--- + 1 + +(2 rows) + +ROLLBACK; +-- IMMV containing user defined type +BEGIN; +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: return type mytype is only a shell +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: argument type mytype is only a shell +LINE 1: CREATE FUNCTION mytype_out(mytype) + ^ +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +NOTICE: could not create an index on materialized view "mv_mytype" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + x +--- + 1 +(1 row) + +ROLLBACK; +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +ERROR: OUTER JOIN is not supported on incrementally maintainable materialized view +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +ERROR: CTE is not supported on incrementally maintainable materialized view +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +ERROR: ORDER BY clause is not supported on incrementally maintainable materialized view +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; +ERROR: HAVING clause is not supported on incrementally maintainable materialized view +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; +ERROR: mutable function is not supported on incrementally maintainable materialized view +HINT: functions must be marked IMMUTABLE +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; +ERROR: LIMIT/OFFSET clause is not supported on incrementally maintainable materialized view +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; +ERROR: DISTINCT is not supported on incrementally maintainable materialized view +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); +ERROR: TABLESAMPLE clause is not supported on incrementally maintainable materialized view +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; +ERROR: window functions are not supported on incrementally maintainable materialized view +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ERROR: inheritance parent is not supported on incrementally maintainable materialized view +ROLLBACK; +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; +ERROR: UNION/INTERSECT/EXCEPT statements are not supported on incrementally maintainable materialized view +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; +ERROR: empty target list is not supported on incrementally maintainable materialized view +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; +ERROR: FOR UPDATE/SHARE clause is not supported on incrementally maintainable materialized view +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; +ERROR: column name __ivm_count__ is not supported on incrementally maintainable materialized view +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; +ERROR: aggregate function is not supported on incrementally maintainable materialized view +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); +ERROR: VALUES is not supported on incrementally maintainable materialized view +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +NOTICE: role "regress_ivm_admin" does not exist, skipping +DROP USER IF EXISTS regress_ivm_user; +NOTICE: role "regress_ivm_user" does not exist, skipping +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +NOTICE: could not create an index on materialized view "ivm_rls" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user +(1 row) + +RESET SESSION AUTHORIZATION; +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user + 3 | baz | regress_ivm_user +(2 rows) + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +-- +(1 row) + +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+-------+------------------ + 2 | bar | regress_ivm_user + 3 | baz | regress_ivm_user + 6 | corge | regress_ivm_user +(3 rows) + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +NOTICE: could not create an index on materialized view "ivm_rls2" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +RESET SESSION AUTHORIZATION; +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +-- +(1 row) + +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + id | data | owner | num +----+-------+------------------+--------- + 2 | bar | regress_ivm_user | two + 3 | baz_2 | regress_ivm_user | three_2 + 6 | corge | regress_ivm_user | six +(3 rows) + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +NOTICE: could not create an index on materialized view "mv_update_same" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + i +--- + 2 +(1 row) + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +NOTICE: created index "mv_self_ref_index" on materialized view "mv_self_ref" +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; + a | b +----+---- + 11 | + 12 | 11 + 13 | 12 +(3 rows) + +ROLLBACK; +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; +NOTICE: created index "mv_idx3_index" on materialized view "mv_idx3" +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +NOTICE: could not create an index on materialized view "mv_idx4" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; +NOTICE: could not create an index on materialized view "mv_idx5" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); +NOTICE: could not create an index on materialized view "mv_idx6" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ERROR: data type json has no default operator class for access method "btree" +ROLLBACK; +-- cleanup +DROP TABLE rls_tbl CASCADE; +NOTICE: drop cascades to 2 other objects +DETAIL: drop cascades to materialized view ivm_rls +drop cascades to materialized view ivm_rls2 +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; +DROP TABLE mv_base_b CASCADE; +NOTICE: drop cascades to 3 other objects +DETAIL: drop cascades to materialized view mv_ivm_1 +drop cascades to view b_view +drop cascades to materialized view b_mview +DROP TABLE mv_base_a CASCADE; diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index 8fa0a6c47fb..7caca5f64fd 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -77,6 +77,7 @@ test: brin_bloom brin_multi # Another group of parallel tests # ---------- test: create_table_like alter_generic alter_operator misc async dbsize merge misc_functions nls sysviews tsrf tid tidscan tidrangescan collate.utf8 collate.icu.utf8 incremental_sort create_role without_overlaps generated_virtual +test: incremental_matview # collate.linux.utf8 and collate.icu.utf8 tests cannot be run in parallel with each other # psql depends on create_am diff --git a/src/test/regress/sql/incremental_matview.sql b/src/test/regress/sql/incremental_matview.sql new file mode 100644 index 00000000000..7313ad82f3e --- /dev/null +++ b/src/test/regress/sql/incremental_matview.sql @@ -0,0 +1,407 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); + +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +REFRESH MATERIALIZED VIEW mv_ivm_1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; + +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; +ROLLBACK; + +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- DISTINCT not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT * FROM mv_base_a; + +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; + + +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +ROLLBACK; + +-- result of materialized view have duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +ROLLBACK; + +-- aggregate not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; + +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +SELECT * FROM mv_self ORDER BY v1; +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; +SELECT * FROM mv_self ORDER BY v1; + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + +ROLLBACK; + +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +SELECT * FROM mv ORDER BY v1; +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; +SELECT * FROM mv ORDER BY v1; +ROLLBACK; + +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +SELECT * FROM mv_ri ORDER BY i1; +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; +ROLLBACK; + +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +-- IMMV containing user defined type +BEGIN; + +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); + +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; + +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); + +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); + +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + +ROLLBACK; + +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; + +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; + +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; + +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; + +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; + +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); + +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; + +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ROLLBACK; + +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; + +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; + +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; + +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; + +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; + +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); + +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +DROP USER IF EXISTS regress_ivm_user; +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; + +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); + +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; + +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; + +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; +RESET SESSION AUTHORIZATION; + +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +RESET SESSION AUTHORIZATION; + +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; +ROLLBACK; + +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); + +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; + +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; + +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); + +ROLLBACK; + +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ROLLBACK; + +-- cleanup + +DROP TABLE rls_tbl CASCADE; +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; + +DROP TABLE mv_base_b CASCADE; +DROP TABLE mv_base_a CASCADE; -- 2.43.0 --Multipart=_Fri__3_Jul_2026_19_11_16_+0900_CskxSIu_iGcDMEyM Content-Type: text/x-diff; name="v39-0006-Add-Incremental-View-Maintenance-support.patch" Content-Disposition: attachment; filename="v39-0006-Add-Incremental-View-Maintenance-support.patch" Content-Transfer-Encoding: 7bit ^ permalink raw reply [nested|flat] 78+ messages in thread
* [PATCH v39 7/8] Add regression tests for Incremental View Maintenance @ 2026-05-29 09:31 Yugo Nagata <[email protected]> 0 siblings, 0 replies; 78+ messages in thread From: Yugo Nagata @ 2026-05-29 09:31 UTC (permalink / raw) --- .../isolation/expected/ivm-create-insert.out | 285 ++++++++ .../isolation/expected/ivm-create-insert2.out | 305 ++++++++ .../isolation/expected/ivm-create-insert3.out | 305 ++++++++ .../isolation/expected/ivm-insert-insert.out | 497 +++++++++++++ .../isolation/expected/ivm-insert-insert2.out | 373 ++++++++++ .../isolation/expected/ivm-insert-insert3.out | 373 ++++++++++ .../isolation/expected/ivm-refresh-insert.out | 213 ++++++ .../expected/ivm-refresh-insert2.out | 191 +++++ .../expected/ivm-refresh-insert3.out | 191 +++++ src/test/isolation/isolation_schedule | 9 + .../isolation/specs/ivm-create-insert.spec | 47 ++ .../isolation/specs/ivm-create-insert2.spec | 54 ++ .../isolation/specs/ivm-create-insert3.spec | 54 ++ .../isolation/specs/ivm-insert-insert.spec | 62 ++ .../isolation/specs/ivm-insert-insert2.spec | 62 ++ .../isolation/specs/ivm-insert-insert3.spec | 62 ++ .../isolation/specs/ivm-refresh-insert.spec | 46 ++ .../isolation/specs/ivm-refresh-insert2.spec | 46 ++ .../isolation/specs/ivm-refresh-insert3.spec | 46 ++ .../regress/expected/incremental_matview.out | 667 ++++++++++++++++++ src/test/regress/parallel_schedule | 1 + src/test/regress/sql/incremental_matview.sql | 407 +++++++++++ 22 files changed, 4296 insertions(+) create mode 100644 src/test/isolation/expected/ivm-create-insert.out create mode 100644 src/test/isolation/expected/ivm-create-insert2.out create mode 100644 src/test/isolation/expected/ivm-create-insert3.out create mode 100644 src/test/isolation/expected/ivm-insert-insert.out create mode 100644 src/test/isolation/expected/ivm-insert-insert2.out create mode 100644 src/test/isolation/expected/ivm-insert-insert3.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert2.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert3.out create mode 100644 src/test/isolation/specs/ivm-create-insert.spec create mode 100644 src/test/isolation/specs/ivm-create-insert2.spec create mode 100644 src/test/isolation/specs/ivm-create-insert3.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert2.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert3.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert2.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert3.spec create mode 100644 src/test/regress/expected/incremental_matview.out create mode 100644 src/test/regress/sql/incremental_matview.sql diff --git a/src/test/isolation/expected/ivm-create-insert.out b/src/test/isolation/expected/ivm-create-insert.out new file mode 100644 index 00000000000..5da00043aba --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert.out @@ -0,0 +1,285 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-create-insert2.out b/src/test/isolation/expected/ivm-create-insert2.out new file mode 100644 index 00000000000..907d892c6d4 --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert2.out @@ -0,0 +1,305 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + diff --git a/src/test/isolation/expected/ivm-create-insert3.out b/src/test/isolation/expected/ivm-create-insert3.out new file mode 100644 index 00000000000..907d892c6d4 --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert3.out @@ -0,0 +1,305 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert.out b/src/test/isolation/expected/ivm-insert-insert.out new file mode 100644 index 00000000000..5ca4cfea677 --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert.out @@ -0,0 +1,497 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; <waiting ...> +step c1: COMMIT; +step update2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; <waiting ...> +step c1: COMMIT; +step update2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; <waiting ...> +step c2: COMMIT; +step update1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; <waiting ...> +step c2: COMMIT; +step update1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); <waiting ...> +step c1: COMMIT; +step insert2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); <waiting ...> +step c1: COMMIT; +step insert2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); <waiting ...> +step c2: COMMIT; +step insert1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); <waiting ...> +step c2: COMMIT; +step insert1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert2.out b/src/test/isolation/expected/ivm-insert-insert2.out new file mode 100644 index 00000000000..e1c66d4de5e --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert2.out @@ -0,0 +1,373 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert3.out b/src/test/isolation/expected/ivm-insert-insert3.out new file mode 100644 index 00000000000..e1c66d4de5e --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert3.out @@ -0,0 +1,373 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert.out b/src/test/isolation/expected/ivm-refresh-insert.out new file mode 100644 index 00000000000..a925938bf1c --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert.out @@ -0,0 +1,213 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert2.out b/src/test/isolation/expected/ivm-refresh-insert2.out new file mode 100644 index 00000000000..dc1b16ae34e --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert2.out @@ -0,0 +1,191 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert3.out b/src/test/isolation/expected/ivm-refresh-insert3.out new file mode 100644 index 00000000000..dc1b16ae34e --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert3.out @@ -0,0 +1,191 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/isolation_schedule b/src/test/isolation/isolation_schedule index b8ebe92553c..6b7e873b370 100644 --- a/src/test/isolation/isolation_schedule +++ b/src/test/isolation/isolation_schedule @@ -128,3 +128,12 @@ test: matview-write-skew test: lock-nowait test: for-portion-of test: ddl-dependency-locking +test: ivm-create-insert +test: ivm-create-insert2 +test: ivm-create-insert3 +test: ivm-insert-insert +test: ivm-insert-insert2 +test: ivm-insert-insert3 +test: ivm-refresh-insert +test: ivm-refresh-insert2 +test: ivm-refresh-insert3 diff --git a/src/test/isolation/specs/ivm-create-insert.spec b/src/test/isolation/specs/ivm-create-insert.spec new file mode 100644 index 00000000000..ccd6fd080a9 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert.spec @@ -0,0 +1,47 @@ +# Test interaction between concurrent transactions performing +# create and insert in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-create-insert2.spec b/src/test/isolation/specs/ivm-create-insert2.spec new file mode 100644 index 00000000000..02cec85ae07 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert2.spec @@ -0,0 +1,54 @@ +# Test interaction between concurrent transactions performing +# create and insert in REPEATABLE READ isolation level +# +# Note: +# In this isolation level, it is possible that create_immv could +# create an inconsistent view not including effects of a concurrent +# transaction. So, an warning message is raised to suggest using it +# in READ COMMITTED or executing refresh_immv to make sure to +# make the view contents consistent. + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-create-insert3.spec b/src/test/isolation/specs/ivm-create-insert3.spec new file mode 100644 index 00000000000..19ce03185a4 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert3.spec @@ -0,0 +1,54 @@ +# Test interaction between concurrent transactions performing +# create and insert in SERIALIZABLE isolation level +# +# Note: +# In this isolation level, it is possible that create_immv could +# create an inconsistent view not including effects of a concurrent +# transaction. So, an warning message is raised to suggest using it +# in READ COMMITTED or executing refresh_immv to make sure to +# make the view contents consistent. + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert.spec b/src/test/isolation/specs/ivm-insert-insert.spec new file mode 100644 index 00000000000..b8f794ca191 --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert2.spec b/src/test/isolation/specs/ivm-insert-insert2.spec new file mode 100644 index 00000000000..ed086d1ba1e --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert2.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in REPEATABLE READ isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert3.spec b/src/test/isolation/specs/ivm-insert-insert3.spec new file mode 100644 index 00000000000..b18bd121033 --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert3.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in SERIALIZABLE isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert.spec b/src/test/isolation/specs/ivm-refresh-insert.spec new file mode 100644 index 00000000000..d7181251962 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert2.spec b/src/test/isolation/specs/ivm-refresh-insert2.spec new file mode 100644 index 00000000000..f2d1d5013f2 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert2.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in REPEATABLE READ isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert3.spec b/src/test/isolation/specs/ivm-refresh-insert3.spec new file mode 100644 index 00000000000..0ec2b1d1de0 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert3.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in SERIALIZABLE isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/regress/expected/incremental_matview.out b/src/test/regress/expected/incremental_matview.out new file mode 100644 index 00000000000..c7fd19fdca3 --- /dev/null +++ b/src/test/regress/expected/incremental_matview.out @@ -0,0 +1,667 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ERROR: materialized view "mv_ivm_1" has not been populated +HINT: Use the REFRESH MATERIALIZED VIEW command. +REFRESH MATERIALIZED VIEW mv_ivm_1; +NOTICE: could not create an index on materialized view "mv_ivm_1" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 17 +(1 row) + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 1 +(1 row) + +ROLLBACK; +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- DISTINCT not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT * FROM mv_base_a; +ERROR: DISTINCT is not supported on incrementally maintainable materialized view +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +NOTICE: could not create an index on materialized view "mv_ivm_func" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +NOTICE: could not create an index on materialized view "mv_ivm_no_tbl" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- result of materialized view have duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_duplicate" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 20 + 30 + 40 + 50 +(6 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +ROLLBACK; +-- aggregate not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +ERROR: aggregate function is not supported on incrementally maintainable materialized view +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +NOTICE: could not create an index on materialized view "mv_self" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +----+---- + 10 | 10 + 20 | 20 + 30 | 30 +(3 rows) + +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 30 | 30 + 40 | 40 + 200 | 200 +(3 rows) + +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 130 | 130 + 300 | 300 +(4 rows) + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 70 | 70 + 70 | 77 + 77 | 70 + 77 | 77 + 130 | 130 + 300 | 300 +(8 rows) + +ROLLBACK; +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY v1; + v1 | v2 +----+----- + 10 | 100 + 20 | 200 + 30 | 300 +(3 rows) + +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv ORDER BY v1; + v1 | v2 +------+----- + 10 | 100 + 11 | 100 + 1020 | 200 + 1020 | 222 +(4 rows) + +ROLLBACK; +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +NOTICE: created index "mv_ri_index" on materialized view "mv_ri" +SELECT * FROM mv_ri ORDER BY i1; + i1 | i2 +----+---- + 1 | 1 + 2 | 2 + 3 | 3 +(3 rows) + +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; + i1 | i2 +----+---- + 3 | 3 + 10 | 10 +(2 rows) + +ROLLBACK; +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | +(2 rows) + +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | 20 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i +--- +(0 rows) + +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; + i +--- + 1 + +(2 rows) + +ROLLBACK; +-- IMMV containing user defined type +BEGIN; +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: return type mytype is only a shell +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: argument type mytype is only a shell +LINE 1: CREATE FUNCTION mytype_out(mytype) + ^ +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +NOTICE: could not create an index on materialized view "mv_mytype" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + x +--- + 1 +(1 row) + +ROLLBACK; +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +ERROR: OUTER JOIN is not supported on incrementally maintainable materialized view +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +ERROR: CTE is not supported on incrementally maintainable materialized view +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +ERROR: ORDER BY clause is not supported on incrementally maintainable materialized view +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; +ERROR: HAVING clause is not supported on incrementally maintainable materialized view +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; +ERROR: mutable function is not supported on incrementally maintainable materialized view +HINT: functions must be marked IMMUTABLE +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; +ERROR: LIMIT/OFFSET clause is not supported on incrementally maintainable materialized view +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; +ERROR: DISTINCT is not supported on incrementally maintainable materialized view +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); +ERROR: TABLESAMPLE clause is not supported on incrementally maintainable materialized view +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; +ERROR: window functions are not supported on incrementally maintainable materialized view +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ERROR: inheritance parent is not supported on incrementally maintainable materialized view +ROLLBACK; +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; +ERROR: UNION/INTERSECT/EXCEPT statements are not supported on incrementally maintainable materialized view +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; +ERROR: empty target list is not supported on incrementally maintainable materialized view +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; +ERROR: FOR UPDATE/SHARE clause is not supported on incrementally maintainable materialized view +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; +ERROR: column name __ivm_count__ is not supported on incrementally maintainable materialized view +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; +ERROR: aggregate function is not supported on incrementally maintainable materialized view +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); +ERROR: VALUES is not supported on incrementally maintainable materialized view +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +NOTICE: role "regress_ivm_admin" does not exist, skipping +DROP USER IF EXISTS regress_ivm_user; +NOTICE: role "regress_ivm_user" does not exist, skipping +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +NOTICE: could not create an index on materialized view "ivm_rls" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user +(1 row) + +RESET SESSION AUTHORIZATION; +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user + 3 | baz | regress_ivm_user +(2 rows) + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +-- +(1 row) + +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+-------+------------------ + 2 | bar | regress_ivm_user + 3 | baz | regress_ivm_user + 6 | corge | regress_ivm_user +(3 rows) + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +NOTICE: could not create an index on materialized view "ivm_rls2" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +RESET SESSION AUTHORIZATION; +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +-- +(1 row) + +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + id | data | owner | num +----+-------+------------------+--------- + 2 | bar | regress_ivm_user | two + 3 | baz_2 | regress_ivm_user | three_2 + 6 | corge | regress_ivm_user | six +(3 rows) + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +NOTICE: could not create an index on materialized view "mv_update_same" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + i +--- + 2 +(1 row) + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +NOTICE: created index "mv_self_ref_index" on materialized view "mv_self_ref" +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; + a | b +----+---- + 11 | + 12 | 11 + 13 | 12 +(3 rows) + +ROLLBACK; +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; +NOTICE: created index "mv_idx3_index" on materialized view "mv_idx3" +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +NOTICE: could not create an index on materialized view "mv_idx4" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; +NOTICE: could not create an index on materialized view "mv_idx5" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); +NOTICE: could not create an index on materialized view "mv_idx6" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ERROR: data type json has no default operator class for access method "btree" +ROLLBACK; +-- cleanup +DROP TABLE rls_tbl CASCADE; +NOTICE: drop cascades to 2 other objects +DETAIL: drop cascades to materialized view ivm_rls +drop cascades to materialized view ivm_rls2 +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; +DROP TABLE mv_base_b CASCADE; +NOTICE: drop cascades to 3 other objects +DETAIL: drop cascades to materialized view mv_ivm_1 +drop cascades to view b_view +drop cascades to materialized view b_mview +DROP TABLE mv_base_a CASCADE; diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index 8fa0a6c47fb..7caca5f64fd 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -77,6 +77,7 @@ test: brin_bloom brin_multi # Another group of parallel tests # ---------- test: create_table_like alter_generic alter_operator misc async dbsize merge misc_functions nls sysviews tsrf tid tidscan tidrangescan collate.utf8 collate.icu.utf8 incremental_sort create_role without_overlaps generated_virtual +test: incremental_matview # collate.linux.utf8 and collate.icu.utf8 tests cannot be run in parallel with each other # psql depends on create_am diff --git a/src/test/regress/sql/incremental_matview.sql b/src/test/regress/sql/incremental_matview.sql new file mode 100644 index 00000000000..7313ad82f3e --- /dev/null +++ b/src/test/regress/sql/incremental_matview.sql @@ -0,0 +1,407 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); + +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +REFRESH MATERIALIZED VIEW mv_ivm_1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; + +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; +ROLLBACK; + +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- DISTINCT not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT * FROM mv_base_a; + +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; + + +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +ROLLBACK; + +-- result of materialized view have duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +ROLLBACK; + +-- aggregate not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; + +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +SELECT * FROM mv_self ORDER BY v1; +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; +SELECT * FROM mv_self ORDER BY v1; + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + +ROLLBACK; + +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +SELECT * FROM mv ORDER BY v1; +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; +SELECT * FROM mv ORDER BY v1; +ROLLBACK; + +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +SELECT * FROM mv_ri ORDER BY i1; +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; +ROLLBACK; + +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +-- IMMV containing user defined type +BEGIN; + +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); + +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; + +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); + +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); + +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + +ROLLBACK; + +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; + +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; + +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; + +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; + +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; + +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); + +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; + +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ROLLBACK; + +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; + +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; + +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; + +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; + +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; + +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); + +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +DROP USER IF EXISTS regress_ivm_user; +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; + +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); + +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; + +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; + +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; +RESET SESSION AUTHORIZATION; + +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +RESET SESSION AUTHORIZATION; + +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; +ROLLBACK; + +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); + +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; + +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; + +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); + +ROLLBACK; + +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ROLLBACK; + +-- cleanup + +DROP TABLE rls_tbl CASCADE; +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; + +DROP TABLE mv_base_b CASCADE; +DROP TABLE mv_base_a CASCADE; -- 2.43.0 --Multipart=_Fri__3_Jul_2026_19_11_16_+0900_CskxSIu_iGcDMEyM Content-Type: text/x-diff; name="v39-0006-Add-Incremental-View-Maintenance-support.patch" Content-Disposition: attachment; filename="v39-0006-Add-Incremental-View-Maintenance-support.patch" Content-Transfer-Encoding: 7bit ^ permalink raw reply [nested|flat] 78+ messages in thread
* [PATCH v37 10/11] Add regression tests for Incremental View Maintenance @ 2026-05-29 09:31 Yugo Nagata <[email protected]> 0 siblings, 0 replies; 78+ messages in thread From: Yugo Nagata @ 2026-05-29 09:31 UTC (permalink / raw) --- src/test/isolation/isolation_schedule | 9 + .../regress/expected/incremental_matview.out | 1100 +++++++++++++++++ src/test/regress/parallel_schedule | 1 + src/test/regress/sql/incremental_matview.sql | 580 +++++++++ 4 files changed, 1690 insertions(+) create mode 100644 src/test/regress/expected/incremental_matview.out create mode 100644 src/test/regress/sql/incremental_matview.sql diff --git a/src/test/isolation/isolation_schedule b/src/test/isolation/isolation_schedule index 15c33fad4c5..111fd465207 100644 --- a/src/test/isolation/isolation_schedule +++ b/src/test/isolation/isolation_schedule @@ -127,3 +127,12 @@ test: matview-write-skew test: lock-nowait test: for-portion-of test: ddl-dependency-locking +test: ivm-create-insert +test: ivm-create-insert2 +test: ivm-create-insert3 +test: ivm-insert-insert +test: ivm-insert-insert2 +test: ivm-insert-insert3 +test: ivm-refresh-insert +test: ivm-refresh-insert2 +test: ivm-refresh-insert3 diff --git a/src/test/regress/expected/incremental_matview.out b/src/test/regress/expected/incremental_matview.out new file mode 100644 index 00000000000..f215aa88e48 --- /dev/null +++ b/src/test/regress/expected/incremental_matview.out @@ -0,0 +1,1100 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ERROR: materialized view "mv_ivm_1" has not been populated +HINT: Use the REFRESH MATERIALIZED VIEW command. +REFRESH MATERIALIZED VIEW mv_ivm_1; +NOTICE: could not create an index on materialized view "mv_ivm_1" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 17 +(1 row) + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 1 +(1 row) + +ROLLBACK; +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_rename_index" on materialized view "mv_ivm_rename" +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +ERROR: IVM column can not be renamed +DROP MATERIALIZED VIEW mv_ivm_rename; +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_unique_index" on materialized view "mv_ivm_unique" +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +ERROR: unique index creation on IVM columns is not supported +DROP MATERIALIZED VIEW mv_ivm_unique; +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +NOTICE: could not create an index on materialized view "mv_ivm_func" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +NOTICE: could not create an index on materialized view "mv_ivm_no_tbl" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_duplicate" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +NOTICE: created index "mv_ivm_distinct_index" on materialized view "mv_ivm_distinct" +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 20 + 30 + 40 + 50 +(6 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +ROLLBACK; +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 120 | 2 | 60.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+---------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 220 | 2 | 110.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 20 | 1 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 120 | 2 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; + sum | count +-----+------- +(0 rows) + +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; + i | sum | count +---+-----+------- +(0 rows) + +ROLLBACK; +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 150 | 5 | 30.0000000000000000 +(1 row) + +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 210 | 6 | 35.0000000000000000 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +NOTICE: created index "mv_ivm_avg_bug_index" on materialized view "mv_ivm_avg_bug" +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 3 | 3.3333333333333333 + 2 | 80 | 3 | 26.6666666666666667 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_min_max_index" on materialized view "mv_ivm_min_max" +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 10 + 2 | 20 | 20 + 3 | 30 | 30 + 4 | 40 | 40 + 5 | 50 | 50 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 12 + 2 | 20 | 22 + 3 | 30 | 32 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 11 | 12 + 2 | 20 | 22 + 3 | 30 | 31 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min_max" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 50 +(1 row) + +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 0 | 70 +(1 row) + +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 60 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + | +(1 row) + +ROLLBACK; +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min; + min +----- + 10 +(1 row) + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + min +----- + 20 +(1 row) + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; + min +----- + 30 +(1 row) + +ROLLBACK; +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | sum +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | b +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ERROR: too many column names were specified +ROLLBACK; +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +NOTICE: could not create an index on materialized view "mv_self" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +----+---- + 10 | 10 + 20 | 20 + 30 | 30 +(3 rows) + +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 30 | 30 + 40 | 40 + 200 | 200 +(3 rows) + +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 130 | 130 + 300 | 300 +(4 rows) + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 70 | 70 + 70 | 77 + 77 | 70 + 77 | 77 + 130 | 130 + 300 | 300 +(8 rows) + +ROLLBACK; +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY v1; + v1 | v2 +----+----- + 10 | 100 + 20 | 200 + 30 | 300 +(3 rows) + +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv ORDER BY v1; + v1 | v2 +------+----- + 10 | 100 + 11 | 100 + 1020 | 200 + 1020 | 222 +(4 rows) + +ROLLBACK; +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +NOTICE: created index "mv_ri_index" on materialized view "mv_ri" +SELECT * FROM mv_ri ORDER BY i1; + i1 | i2 +----+---- + 1 | 1 + 2 | 2 + 3 | 3 +(3 rows) + +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; + i1 | i2 +----+---- + 3 | 3 + 10 | 10 +(2 rows) + +ROLLBACK; +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | +(2 rows) + +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | 20 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i +--- +(0 rows) + +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; + i +--- + 1 + +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 30 + | 3 +(2 rows) + +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 300 + | 30 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 1 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 4 +(1 row) + +ROLLBACK; +-- IMMV containing user defined type +BEGIN; +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: return type mytype is only a shell +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: argument type mytype is only a shell +LINE 1: CREATE FUNCTION mytype_out(mytype) + ^ +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +NOTICE: could not create an index on materialized view "mv_mytype" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + x +--- + 1 +(1 row) + +ROLLBACK; +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +ERROR: OUTER JOIN is not supported on incrementally maintainable materialized view +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +ERROR: CTE is not supported on incrementally maintainable materialized view +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +ERROR: ORDER BY clause is not supported on incrementally maintainable materialized view +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; +ERROR: HAVING clause is not supported on incrementally maintainable materialized view +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; +ERROR: mutable function is not supported on incrementally maintainable materialized view +HINT: functions must be marked IMMUTABLE +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; +ERROR: LIMIT/OFFSET clause is not supported on incrementally maintainable materialized view +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; +ERROR: DISTINCT ON is not supported on incrementally maintainable materialized view +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); +ERROR: TABLESAMPLE clause is not supported on incrementally maintainable materialized view +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; +ERROR: window functions are not supported on incrementally maintainable materialized view +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +ERROR: aggregate function with FILTER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +ERROR: aggregate function with DISTINCT arguments is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +ERROR: aggregate function with ORDER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); +ERROR: GROUPING SETS, ROLLUP, or CUBE clauses is not supported on incrementally maintainable materialized view +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ERROR: inheritance parent is not supported on incrementally maintainable materialized view +ROLLBACK; +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; +ERROR: UNION/INTERSECT/EXCEPT statements are not supported on incrementally maintainable materialized view +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; +ERROR: empty target list is not supported on incrementally maintainable materialized view +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; +ERROR: FOR UPDATE/SHARE clause is not supported on incrementally maintainable materialized view +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; +ERROR: column name __ivm_count__ is not supported on incrementally maintainable materialized view +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; +ERROR: GROUP BY expression not appearing in select list is not supported on incrementally maintainable materialized view +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); +ERROR: VALUES is not supported on incrementally maintainable materialized view +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +NOTICE: role "regress_ivm_admin" does not exist, skipping +DROP USER IF EXISTS regress_ivm_user; +NOTICE: role "regress_ivm_user" does not exist, skipping +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +NOTICE: could not create an index on materialized view "ivm_rls" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user +(1 row) + +RESET SESSION AUTHORIZATION; +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user + 3 | baz | regress_ivm_user +(2 rows) + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +-- +(1 row) + +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+-------+------------------ + 2 | bar | regress_ivm_user + 3 | baz | regress_ivm_user + 6 | corge | regress_ivm_user +(3 rows) + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +NOTICE: could not create an index on materialized view "ivm_rls2" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +RESET SESSION AUTHORIZATION; +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +-- +(1 row) + +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + id | data | owner | num +----+-------+------------------+--------- + 2 | bar | regress_ivm_user | two + 3 | baz_2 | regress_ivm_user | three_2 + 6 | corge | regress_ivm_user | six +(3 rows) + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +NOTICE: could not create an index on materialized view "mv_update_same" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + i +--- + 2 +(1 row) + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +NOTICE: created index "mv_self_ref_index" on materialized view "mv_self_ref" +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; + a | b +----+---- + 11 | + 12 | 11 + 13 | 12 +(3 rows) + +ROLLBACK; +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; +NOTICE: created index "mv_idx1_index" on materialized view "mv_idx1" +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; +NOTICE: created index "mv_idx2_index" on materialized view "mv_idx2" +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; +NOTICE: created index "mv_idx3_index" on materialized view "mv_idx3" +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +NOTICE: could not create an index on materialized view "mv_idx4" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; +NOTICE: could not create an index on materialized view "mv_idx5" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); +NOTICE: could not create an index on materialized view "mv_idx6" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ERROR: data type json has no default operator class for access method "btree" +ROLLBACK; +-- cleanup +DROP TABLE rls_tbl CASCADE; +NOTICE: drop cascades to 2 other objects +DETAIL: drop cascades to materialized view ivm_rls +drop cascades to materialized view ivm_rls2 +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; +DROP TABLE mv_base_b CASCADE; +NOTICE: drop cascades to 3 other objects +DETAIL: drop cascades to materialized view mv_ivm_1 +drop cascades to view b_view +drop cascades to materialized view b_mview +DROP TABLE mv_base_a CASCADE; diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index 8fa0a6c47fb..7caca5f64fd 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -77,6 +77,7 @@ test: brin_bloom brin_multi # Another group of parallel tests # ---------- test: create_table_like alter_generic alter_operator misc async dbsize merge misc_functions nls sysviews tsrf tid tidscan tidrangescan collate.utf8 collate.icu.utf8 incremental_sort create_role without_overlaps generated_virtual +test: incremental_matview # collate.linux.utf8 and collate.icu.utf8 tests cannot be run in parallel with each other # psql depends on create_am diff --git a/src/test/regress/sql/incremental_matview.sql b/src/test/regress/sql/incremental_matview.sql new file mode 100644 index 00000000000..2d55c393d6f --- /dev/null +++ b/src/test/regress/sql/incremental_matview.sql @@ -0,0 +1,580 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); + +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +REFRESH MATERIALIZED VIEW mv_ivm_1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; + +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; +ROLLBACK; + +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +DROP MATERIALIZED VIEW mv_ivm_rename; + +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +DROP MATERIALIZED VIEW mv_ivm_unique; + +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; + + +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +ROLLBACK; + +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +ROLLBACK; + +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +ROLLBACK; + +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +ROLLBACK; + +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +ROLLBACK; + +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min; + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); + +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; +ROLLBACK; + +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +SELECT * FROM mv_self ORDER BY v1; +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; +SELECT * FROM mv_self ORDER BY v1; + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + +ROLLBACK; + +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +SELECT * FROM mv ORDER BY v1; +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; +SELECT * FROM mv ORDER BY v1; +ROLLBACK; + +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +SELECT * FROM mv_ri ORDER BY i1; +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; +ROLLBACK; + +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +-- IMMV containing user defined type +BEGIN; + +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); + +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; + +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); + +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); + +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + +ROLLBACK; + +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; + +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; + +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; + +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; + +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; + +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); + +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; + +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); + +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ROLLBACK; + +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; + +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; + +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; + +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; + +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; + +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; + +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); + +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +DROP USER IF EXISTS regress_ivm_user; +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; + +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); + +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; + +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; + +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; +RESET SESSION AUTHORIZATION; + +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +RESET SESSION AUTHORIZATION; + +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; +ROLLBACK; + +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); + +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; + +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; + +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; + +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; + +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); + +ROLLBACK; + +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ROLLBACK; + +-- cleanup + +DROP TABLE rls_tbl CASCADE; +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; + +DROP TABLE mv_base_b CASCADE; +DROP TABLE mv_base_a CASCADE; -- 2.43.0 --Multipart=_Fri__29_May_2026_23_14_17_+0900_Te0o73X2VqYK57Gd Content-Type: text/x-diff; name="v37-0009-Add-support-for-min-max-aggregates-for-IVM.patch" Content-Disposition: attachment; filename="v37-0009-Add-support-for-min-max-aggregates-for-IVM.patch" Content-Transfer-Encoding: 7bit ^ permalink raw reply [nested|flat] 78+ messages in thread
* [PATCH v37 10/11] Add regression tests for Incremental View Maintenance @ 2026-05-29 09:31 Yugo Nagata <[email protected]> 0 siblings, 0 replies; 78+ messages in thread From: Yugo Nagata @ 2026-05-29 09:31 UTC (permalink / raw) --- src/test/isolation/isolation_schedule | 9 + .../regress/expected/incremental_matview.out | 1100 +++++++++++++++++ src/test/regress/parallel_schedule | 1 + src/test/regress/sql/incremental_matview.sql | 580 +++++++++ 4 files changed, 1690 insertions(+) create mode 100644 src/test/regress/expected/incremental_matview.out create mode 100644 src/test/regress/sql/incremental_matview.sql diff --git a/src/test/isolation/isolation_schedule b/src/test/isolation/isolation_schedule index 15c33fad4c5..111fd465207 100644 --- a/src/test/isolation/isolation_schedule +++ b/src/test/isolation/isolation_schedule @@ -127,3 +127,12 @@ test: matview-write-skew test: lock-nowait test: for-portion-of test: ddl-dependency-locking +test: ivm-create-insert +test: ivm-create-insert2 +test: ivm-create-insert3 +test: ivm-insert-insert +test: ivm-insert-insert2 +test: ivm-insert-insert3 +test: ivm-refresh-insert +test: ivm-refresh-insert2 +test: ivm-refresh-insert3 diff --git a/src/test/regress/expected/incremental_matview.out b/src/test/regress/expected/incremental_matview.out new file mode 100644 index 00000000000..f215aa88e48 --- /dev/null +++ b/src/test/regress/expected/incremental_matview.out @@ -0,0 +1,1100 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ERROR: materialized view "mv_ivm_1" has not been populated +HINT: Use the REFRESH MATERIALIZED VIEW command. +REFRESH MATERIALIZED VIEW mv_ivm_1; +NOTICE: could not create an index on materialized view "mv_ivm_1" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 17 +(1 row) + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 1 +(1 row) + +ROLLBACK; +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_rename_index" on materialized view "mv_ivm_rename" +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +ERROR: IVM column can not be renamed +DROP MATERIALIZED VIEW mv_ivm_rename; +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_unique_index" on materialized view "mv_ivm_unique" +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +ERROR: unique index creation on IVM columns is not supported +DROP MATERIALIZED VIEW mv_ivm_unique; +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +NOTICE: could not create an index on materialized view "mv_ivm_func" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +NOTICE: could not create an index on materialized view "mv_ivm_no_tbl" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_duplicate" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +NOTICE: created index "mv_ivm_distinct_index" on materialized view "mv_ivm_distinct" +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 20 + 30 + 40 + 50 +(6 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +ROLLBACK; +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 120 | 2 | 60.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+---------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 220 | 2 | 110.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 20 | 1 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 120 | 2 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; + sum | count +-----+------- +(0 rows) + +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; + i | sum | count +---+-----+------- +(0 rows) + +ROLLBACK; +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 150 | 5 | 30.0000000000000000 +(1 row) + +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 210 | 6 | 35.0000000000000000 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +NOTICE: created index "mv_ivm_avg_bug_index" on materialized view "mv_ivm_avg_bug" +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 3 | 3.3333333333333333 + 2 | 80 | 3 | 26.6666666666666667 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_min_max_index" on materialized view "mv_ivm_min_max" +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 10 + 2 | 20 | 20 + 3 | 30 | 30 + 4 | 40 | 40 + 5 | 50 | 50 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 12 + 2 | 20 | 22 + 3 | 30 | 32 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 11 | 12 + 2 | 20 | 22 + 3 | 30 | 31 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min_max" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 50 +(1 row) + +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 0 | 70 +(1 row) + +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 60 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + | +(1 row) + +ROLLBACK; +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min; + min +----- + 10 +(1 row) + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + min +----- + 20 +(1 row) + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; + min +----- + 30 +(1 row) + +ROLLBACK; +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | sum +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | b +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ERROR: too many column names were specified +ROLLBACK; +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +NOTICE: could not create an index on materialized view "mv_self" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +----+---- + 10 | 10 + 20 | 20 + 30 | 30 +(3 rows) + +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 30 | 30 + 40 | 40 + 200 | 200 +(3 rows) + +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 130 | 130 + 300 | 300 +(4 rows) + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 70 | 70 + 70 | 77 + 77 | 70 + 77 | 77 + 130 | 130 + 300 | 300 +(8 rows) + +ROLLBACK; +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY v1; + v1 | v2 +----+----- + 10 | 100 + 20 | 200 + 30 | 300 +(3 rows) + +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv ORDER BY v1; + v1 | v2 +------+----- + 10 | 100 + 11 | 100 + 1020 | 200 + 1020 | 222 +(4 rows) + +ROLLBACK; +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +NOTICE: created index "mv_ri_index" on materialized view "mv_ri" +SELECT * FROM mv_ri ORDER BY i1; + i1 | i2 +----+---- + 1 | 1 + 2 | 2 + 3 | 3 +(3 rows) + +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; + i1 | i2 +----+---- + 3 | 3 + 10 | 10 +(2 rows) + +ROLLBACK; +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | +(2 rows) + +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | 20 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i +--- +(0 rows) + +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; + i +--- + 1 + +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 30 + | 3 +(2 rows) + +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 300 + | 30 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 1 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 4 +(1 row) + +ROLLBACK; +-- IMMV containing user defined type +BEGIN; +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: return type mytype is only a shell +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: argument type mytype is only a shell +LINE 1: CREATE FUNCTION mytype_out(mytype) + ^ +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +NOTICE: could not create an index on materialized view "mv_mytype" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + x +--- + 1 +(1 row) + +ROLLBACK; +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +ERROR: OUTER JOIN is not supported on incrementally maintainable materialized view +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +ERROR: CTE is not supported on incrementally maintainable materialized view +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +ERROR: ORDER BY clause is not supported on incrementally maintainable materialized view +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; +ERROR: HAVING clause is not supported on incrementally maintainable materialized view +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; +ERROR: mutable function is not supported on incrementally maintainable materialized view +HINT: functions must be marked IMMUTABLE +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; +ERROR: LIMIT/OFFSET clause is not supported on incrementally maintainable materialized view +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; +ERROR: DISTINCT ON is not supported on incrementally maintainable materialized view +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); +ERROR: TABLESAMPLE clause is not supported on incrementally maintainable materialized view +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; +ERROR: window functions are not supported on incrementally maintainable materialized view +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +ERROR: aggregate function with FILTER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +ERROR: aggregate function with DISTINCT arguments is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +ERROR: aggregate function with ORDER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); +ERROR: GROUPING SETS, ROLLUP, or CUBE clauses is not supported on incrementally maintainable materialized view +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ERROR: inheritance parent is not supported on incrementally maintainable materialized view +ROLLBACK; +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; +ERROR: UNION/INTERSECT/EXCEPT statements are not supported on incrementally maintainable materialized view +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; +ERROR: empty target list is not supported on incrementally maintainable materialized view +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; +ERROR: FOR UPDATE/SHARE clause is not supported on incrementally maintainable materialized view +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; +ERROR: column name __ivm_count__ is not supported on incrementally maintainable materialized view +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; +ERROR: GROUP BY expression not appearing in select list is not supported on incrementally maintainable materialized view +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); +ERROR: VALUES is not supported on incrementally maintainable materialized view +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +NOTICE: role "regress_ivm_admin" does not exist, skipping +DROP USER IF EXISTS regress_ivm_user; +NOTICE: role "regress_ivm_user" does not exist, skipping +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +NOTICE: could not create an index on materialized view "ivm_rls" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user +(1 row) + +RESET SESSION AUTHORIZATION; +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user + 3 | baz | regress_ivm_user +(2 rows) + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +-- +(1 row) + +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+-------+------------------ + 2 | bar | regress_ivm_user + 3 | baz | regress_ivm_user + 6 | corge | regress_ivm_user +(3 rows) + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +NOTICE: could not create an index on materialized view "ivm_rls2" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +RESET SESSION AUTHORIZATION; +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +-- +(1 row) + +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + id | data | owner | num +----+-------+------------------+--------- + 2 | bar | regress_ivm_user | two + 3 | baz_2 | regress_ivm_user | three_2 + 6 | corge | regress_ivm_user | six +(3 rows) + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +NOTICE: could not create an index on materialized view "mv_update_same" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + i +--- + 2 +(1 row) + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +NOTICE: created index "mv_self_ref_index" on materialized view "mv_self_ref" +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; + a | b +----+---- + 11 | + 12 | 11 + 13 | 12 +(3 rows) + +ROLLBACK; +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; +NOTICE: created index "mv_idx1_index" on materialized view "mv_idx1" +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; +NOTICE: created index "mv_idx2_index" on materialized view "mv_idx2" +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; +NOTICE: created index "mv_idx3_index" on materialized view "mv_idx3" +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +NOTICE: could not create an index on materialized view "mv_idx4" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; +NOTICE: could not create an index on materialized view "mv_idx5" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); +NOTICE: could not create an index on materialized view "mv_idx6" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ERROR: data type json has no default operator class for access method "btree" +ROLLBACK; +-- cleanup +DROP TABLE rls_tbl CASCADE; +NOTICE: drop cascades to 2 other objects +DETAIL: drop cascades to materialized view ivm_rls +drop cascades to materialized view ivm_rls2 +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; +DROP TABLE mv_base_b CASCADE; +NOTICE: drop cascades to 3 other objects +DETAIL: drop cascades to materialized view mv_ivm_1 +drop cascades to view b_view +drop cascades to materialized view b_mview +DROP TABLE mv_base_a CASCADE; diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index 8fa0a6c47fb..7caca5f64fd 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -77,6 +77,7 @@ test: brin_bloom brin_multi # Another group of parallel tests # ---------- test: create_table_like alter_generic alter_operator misc async dbsize merge misc_functions nls sysviews tsrf tid tidscan tidrangescan collate.utf8 collate.icu.utf8 incremental_sort create_role without_overlaps generated_virtual +test: incremental_matview # collate.linux.utf8 and collate.icu.utf8 tests cannot be run in parallel with each other # psql depends on create_am diff --git a/src/test/regress/sql/incremental_matview.sql b/src/test/regress/sql/incremental_matview.sql new file mode 100644 index 00000000000..2d55c393d6f --- /dev/null +++ b/src/test/regress/sql/incremental_matview.sql @@ -0,0 +1,580 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); + +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +REFRESH MATERIALIZED VIEW mv_ivm_1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; + +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; +ROLLBACK; + +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +DROP MATERIALIZED VIEW mv_ivm_rename; + +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +DROP MATERIALIZED VIEW mv_ivm_unique; + +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; + + +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +ROLLBACK; + +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +ROLLBACK; + +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +ROLLBACK; + +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +ROLLBACK; + +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +ROLLBACK; + +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min; + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); + +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; +ROLLBACK; + +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +SELECT * FROM mv_self ORDER BY v1; +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; +SELECT * FROM mv_self ORDER BY v1; + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + +ROLLBACK; + +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +SELECT * FROM mv ORDER BY v1; +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; +SELECT * FROM mv ORDER BY v1; +ROLLBACK; + +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +SELECT * FROM mv_ri ORDER BY i1; +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; +ROLLBACK; + +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +-- IMMV containing user defined type +BEGIN; + +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); + +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; + +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); + +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); + +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + +ROLLBACK; + +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; + +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; + +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; + +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; + +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; + +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); + +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; + +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); + +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ROLLBACK; + +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; + +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; + +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; + +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; + +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; + +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; + +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); + +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +DROP USER IF EXISTS regress_ivm_user; +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; + +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); + +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; + +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; + +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; +RESET SESSION AUTHORIZATION; + +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +RESET SESSION AUTHORIZATION; + +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; +ROLLBACK; + +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); + +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; + +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; + +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; + +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; + +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); + +ROLLBACK; + +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ROLLBACK; + +-- cleanup + +DROP TABLE rls_tbl CASCADE; +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; + +DROP TABLE mv_base_b CASCADE; +DROP TABLE mv_base_a CASCADE; -- 2.43.0 --Multipart=_Fri__29_May_2026_23_14_17_+0900_Te0o73X2VqYK57Gd Content-Type: text/x-diff; name="v37-0009-Add-support-for-min-max-aggregates-for-IVM.patch" Content-Disposition: attachment; filename="v37-0009-Add-support-for-min-max-aggregates-for-IVM.patch" Content-Transfer-Encoding: 7bit ^ permalink raw reply [nested|flat] 78+ messages in thread
* [PATCH v37 10/11] Add regression tests for Incremental View Maintenance @ 2026-05-29 09:31 Yugo Nagata <[email protected]> 0 siblings, 0 replies; 78+ messages in thread From: Yugo Nagata @ 2026-05-29 09:31 UTC (permalink / raw) --- src/test/isolation/isolation_schedule | 9 + .../regress/expected/incremental_matview.out | 1100 +++++++++++++++++ src/test/regress/parallel_schedule | 1 + src/test/regress/sql/incremental_matview.sql | 580 +++++++++ 4 files changed, 1690 insertions(+) create mode 100644 src/test/regress/expected/incremental_matview.out create mode 100644 src/test/regress/sql/incremental_matview.sql diff --git a/src/test/isolation/isolation_schedule b/src/test/isolation/isolation_schedule index 15c33fad4c5..111fd465207 100644 --- a/src/test/isolation/isolation_schedule +++ b/src/test/isolation/isolation_schedule @@ -127,3 +127,12 @@ test: matview-write-skew test: lock-nowait test: for-portion-of test: ddl-dependency-locking +test: ivm-create-insert +test: ivm-create-insert2 +test: ivm-create-insert3 +test: ivm-insert-insert +test: ivm-insert-insert2 +test: ivm-insert-insert3 +test: ivm-refresh-insert +test: ivm-refresh-insert2 +test: ivm-refresh-insert3 diff --git a/src/test/regress/expected/incremental_matview.out b/src/test/regress/expected/incremental_matview.out new file mode 100644 index 00000000000..f215aa88e48 --- /dev/null +++ b/src/test/regress/expected/incremental_matview.out @@ -0,0 +1,1100 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ERROR: materialized view "mv_ivm_1" has not been populated +HINT: Use the REFRESH MATERIALIZED VIEW command. +REFRESH MATERIALIZED VIEW mv_ivm_1; +NOTICE: could not create an index on materialized view "mv_ivm_1" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 17 +(1 row) + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 1 +(1 row) + +ROLLBACK; +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_rename_index" on materialized view "mv_ivm_rename" +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +ERROR: IVM column can not be renamed +DROP MATERIALIZED VIEW mv_ivm_rename; +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_unique_index" on materialized view "mv_ivm_unique" +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +ERROR: unique index creation on IVM columns is not supported +DROP MATERIALIZED VIEW mv_ivm_unique; +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +NOTICE: could not create an index on materialized view "mv_ivm_func" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +NOTICE: could not create an index on materialized view "mv_ivm_no_tbl" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_duplicate" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +NOTICE: created index "mv_ivm_distinct_index" on materialized view "mv_ivm_distinct" +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 20 + 30 + 40 + 50 +(6 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +ROLLBACK; +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 120 | 2 | 60.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+---------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 220 | 2 | 110.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 20 | 1 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 120 | 2 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; + sum | count +-----+------- +(0 rows) + +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; + i | sum | count +---+-----+------- +(0 rows) + +ROLLBACK; +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 150 | 5 | 30.0000000000000000 +(1 row) + +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 210 | 6 | 35.0000000000000000 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +NOTICE: created index "mv_ivm_avg_bug_index" on materialized view "mv_ivm_avg_bug" +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 3 | 3.3333333333333333 + 2 | 80 | 3 | 26.6666666666666667 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_min_max_index" on materialized view "mv_ivm_min_max" +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 10 + 2 | 20 | 20 + 3 | 30 | 30 + 4 | 40 | 40 + 5 | 50 | 50 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 12 + 2 | 20 | 22 + 3 | 30 | 32 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 11 | 12 + 2 | 20 | 22 + 3 | 30 | 31 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min_max" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 50 +(1 row) + +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 0 | 70 +(1 row) + +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 60 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + | +(1 row) + +ROLLBACK; +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min; + min +----- + 10 +(1 row) + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + min +----- + 20 +(1 row) + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; + min +----- + 30 +(1 row) + +ROLLBACK; +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | sum +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | b +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ERROR: too many column names were specified +ROLLBACK; +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +NOTICE: could not create an index on materialized view "mv_self" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +----+---- + 10 | 10 + 20 | 20 + 30 | 30 +(3 rows) + +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 30 | 30 + 40 | 40 + 200 | 200 +(3 rows) + +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 130 | 130 + 300 | 300 +(4 rows) + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 70 | 70 + 70 | 77 + 77 | 70 + 77 | 77 + 130 | 130 + 300 | 300 +(8 rows) + +ROLLBACK; +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY v1; + v1 | v2 +----+----- + 10 | 100 + 20 | 200 + 30 | 300 +(3 rows) + +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv ORDER BY v1; + v1 | v2 +------+----- + 10 | 100 + 11 | 100 + 1020 | 200 + 1020 | 222 +(4 rows) + +ROLLBACK; +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +NOTICE: created index "mv_ri_index" on materialized view "mv_ri" +SELECT * FROM mv_ri ORDER BY i1; + i1 | i2 +----+---- + 1 | 1 + 2 | 2 + 3 | 3 +(3 rows) + +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; + i1 | i2 +----+---- + 3 | 3 + 10 | 10 +(2 rows) + +ROLLBACK; +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | +(2 rows) + +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | 20 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i +--- +(0 rows) + +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; + i +--- + 1 + +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 30 + | 3 +(2 rows) + +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 300 + | 30 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 1 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 4 +(1 row) + +ROLLBACK; +-- IMMV containing user defined type +BEGIN; +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: return type mytype is only a shell +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: argument type mytype is only a shell +LINE 1: CREATE FUNCTION mytype_out(mytype) + ^ +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +NOTICE: could not create an index on materialized view "mv_mytype" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + x +--- + 1 +(1 row) + +ROLLBACK; +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +ERROR: OUTER JOIN is not supported on incrementally maintainable materialized view +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +ERROR: CTE is not supported on incrementally maintainable materialized view +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +ERROR: ORDER BY clause is not supported on incrementally maintainable materialized view +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; +ERROR: HAVING clause is not supported on incrementally maintainable materialized view +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; +ERROR: mutable function is not supported on incrementally maintainable materialized view +HINT: functions must be marked IMMUTABLE +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; +ERROR: LIMIT/OFFSET clause is not supported on incrementally maintainable materialized view +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; +ERROR: DISTINCT ON is not supported on incrementally maintainable materialized view +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); +ERROR: TABLESAMPLE clause is not supported on incrementally maintainable materialized view +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; +ERROR: window functions are not supported on incrementally maintainable materialized view +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +ERROR: aggregate function with FILTER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +ERROR: aggregate function with DISTINCT arguments is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +ERROR: aggregate function with ORDER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); +ERROR: GROUPING SETS, ROLLUP, or CUBE clauses is not supported on incrementally maintainable materialized view +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ERROR: inheritance parent is not supported on incrementally maintainable materialized view +ROLLBACK; +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; +ERROR: UNION/INTERSECT/EXCEPT statements are not supported on incrementally maintainable materialized view +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; +ERROR: empty target list is not supported on incrementally maintainable materialized view +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; +ERROR: FOR UPDATE/SHARE clause is not supported on incrementally maintainable materialized view +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; +ERROR: column name __ivm_count__ is not supported on incrementally maintainable materialized view +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; +ERROR: GROUP BY expression not appearing in select list is not supported on incrementally maintainable materialized view +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); +ERROR: VALUES is not supported on incrementally maintainable materialized view +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +NOTICE: role "regress_ivm_admin" does not exist, skipping +DROP USER IF EXISTS regress_ivm_user; +NOTICE: role "regress_ivm_user" does not exist, skipping +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +NOTICE: could not create an index on materialized view "ivm_rls" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user +(1 row) + +RESET SESSION AUTHORIZATION; +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user + 3 | baz | regress_ivm_user +(2 rows) + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +-- +(1 row) + +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+-------+------------------ + 2 | bar | regress_ivm_user + 3 | baz | regress_ivm_user + 6 | corge | regress_ivm_user +(3 rows) + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +NOTICE: could not create an index on materialized view "ivm_rls2" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +RESET SESSION AUTHORIZATION; +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +-- +(1 row) + +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + id | data | owner | num +----+-------+------------------+--------- + 2 | bar | regress_ivm_user | two + 3 | baz_2 | regress_ivm_user | three_2 + 6 | corge | regress_ivm_user | six +(3 rows) + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +NOTICE: could not create an index on materialized view "mv_update_same" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + i +--- + 2 +(1 row) + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +NOTICE: created index "mv_self_ref_index" on materialized view "mv_self_ref" +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; + a | b +----+---- + 11 | + 12 | 11 + 13 | 12 +(3 rows) + +ROLLBACK; +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; +NOTICE: created index "mv_idx1_index" on materialized view "mv_idx1" +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; +NOTICE: created index "mv_idx2_index" on materialized view "mv_idx2" +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; +NOTICE: created index "mv_idx3_index" on materialized view "mv_idx3" +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +NOTICE: could not create an index on materialized view "mv_idx4" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; +NOTICE: could not create an index on materialized view "mv_idx5" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); +NOTICE: could not create an index on materialized view "mv_idx6" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ERROR: data type json has no default operator class for access method "btree" +ROLLBACK; +-- cleanup +DROP TABLE rls_tbl CASCADE; +NOTICE: drop cascades to 2 other objects +DETAIL: drop cascades to materialized view ivm_rls +drop cascades to materialized view ivm_rls2 +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; +DROP TABLE mv_base_b CASCADE; +NOTICE: drop cascades to 3 other objects +DETAIL: drop cascades to materialized view mv_ivm_1 +drop cascades to view b_view +drop cascades to materialized view b_mview +DROP TABLE mv_base_a CASCADE; diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index 8fa0a6c47fb..7caca5f64fd 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -77,6 +77,7 @@ test: brin_bloom brin_multi # Another group of parallel tests # ---------- test: create_table_like alter_generic alter_operator misc async dbsize merge misc_functions nls sysviews tsrf tid tidscan tidrangescan collate.utf8 collate.icu.utf8 incremental_sort create_role without_overlaps generated_virtual +test: incremental_matview # collate.linux.utf8 and collate.icu.utf8 tests cannot be run in parallel with each other # psql depends on create_am diff --git a/src/test/regress/sql/incremental_matview.sql b/src/test/regress/sql/incremental_matview.sql new file mode 100644 index 00000000000..2d55c393d6f --- /dev/null +++ b/src/test/regress/sql/incremental_matview.sql @@ -0,0 +1,580 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); + +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +REFRESH MATERIALIZED VIEW mv_ivm_1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; + +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; +ROLLBACK; + +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +DROP MATERIALIZED VIEW mv_ivm_rename; + +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +DROP MATERIALIZED VIEW mv_ivm_unique; + +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; + + +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +ROLLBACK; + +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +ROLLBACK; + +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +ROLLBACK; + +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +ROLLBACK; + +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +ROLLBACK; + +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min; + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); + +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; +ROLLBACK; + +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +SELECT * FROM mv_self ORDER BY v1; +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; +SELECT * FROM mv_self ORDER BY v1; + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + +ROLLBACK; + +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +SELECT * FROM mv ORDER BY v1; +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; +SELECT * FROM mv ORDER BY v1; +ROLLBACK; + +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +SELECT * FROM mv_ri ORDER BY i1; +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; +ROLLBACK; + +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +-- IMMV containing user defined type +BEGIN; + +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); + +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; + +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); + +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); + +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + +ROLLBACK; + +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; + +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; + +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; + +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; + +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; + +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); + +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; + +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); + +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ROLLBACK; + +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; + +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; + +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; + +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; + +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; + +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; + +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); + +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +DROP USER IF EXISTS regress_ivm_user; +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; + +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); + +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; + +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; + +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; +RESET SESSION AUTHORIZATION; + +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +RESET SESSION AUTHORIZATION; + +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; +ROLLBACK; + +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); + +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; + +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; + +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; + +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; + +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); + +ROLLBACK; + +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ROLLBACK; + +-- cleanup + +DROP TABLE rls_tbl CASCADE; +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; + +DROP TABLE mv_base_b CASCADE; +DROP TABLE mv_base_a CASCADE; -- 2.43.0 --Multipart=_Fri__29_May_2026_23_14_17_+0900_Te0o73X2VqYK57Gd Content-Type: text/x-diff; name="v37-0009-Add-support-for-min-max-aggregates-for-IVM.patch" Content-Disposition: attachment; filename="v37-0009-Add-support-for-min-max-aggregates-for-IVM.patch" Content-Transfer-Encoding: 7bit ^ permalink raw reply [nested|flat] 78+ messages in thread
* [PATCH v38 10/11] Add regression tests for Incremental View Maintenance @ 2026-05-29 09:31 Yugo Nagata <[email protected]> 0 siblings, 0 replies; 78+ messages in thread From: Yugo Nagata @ 2026-05-29 09:31 UTC (permalink / raw) --- .../isolation/expected/ivm-create-insert.out | 285 +++++ .../isolation/expected/ivm-create-insert2.out | 305 +++++ .../isolation/expected/ivm-create-insert3.out | 305 +++++ .../isolation/expected/ivm-insert-insert.out | 497 ++++++++ .../isolation/expected/ivm-insert-insert2.out | 373 ++++++ .../isolation/expected/ivm-insert-insert3.out | 373 ++++++ .../isolation/expected/ivm-refresh-insert.out | 213 ++++ .../expected/ivm-refresh-insert2.out | 191 +++ .../expected/ivm-refresh-insert3.out | 191 +++ src/test/isolation/isolation_schedule | 9 + .../isolation/specs/ivm-create-insert.spec | 47 + .../isolation/specs/ivm-create-insert2.spec | 54 + .../isolation/specs/ivm-create-insert3.spec | 54 + .../isolation/specs/ivm-insert-insert.spec | 62 + .../isolation/specs/ivm-insert-insert2.spec | 62 + .../isolation/specs/ivm-insert-insert3.spec | 62 + .../isolation/specs/ivm-refresh-insert.spec | 46 + .../isolation/specs/ivm-refresh-insert2.spec | 46 + .../isolation/specs/ivm-refresh-insert3.spec | 46 + .../regress/expected/incremental_matview.out | 1100 +++++++++++++++++ src/test/regress/parallel_schedule | 1 + src/test/regress/sql/incremental_matview.sql | 580 +++++++++ 22 files changed, 4902 insertions(+) create mode 100644 src/test/isolation/expected/ivm-create-insert.out create mode 100644 src/test/isolation/expected/ivm-create-insert2.out create mode 100644 src/test/isolation/expected/ivm-create-insert3.out create mode 100644 src/test/isolation/expected/ivm-insert-insert.out create mode 100644 src/test/isolation/expected/ivm-insert-insert2.out create mode 100644 src/test/isolation/expected/ivm-insert-insert3.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert2.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert3.out create mode 100644 src/test/isolation/specs/ivm-create-insert.spec create mode 100644 src/test/isolation/specs/ivm-create-insert2.spec create mode 100644 src/test/isolation/specs/ivm-create-insert3.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert2.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert3.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert2.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert3.spec create mode 100644 src/test/regress/expected/incremental_matview.out create mode 100644 src/test/regress/sql/incremental_matview.sql diff --git a/src/test/isolation/expected/ivm-create-insert.out b/src/test/isolation/expected/ivm-create-insert.out new file mode 100644 index 00000000000..5da00043aba --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert.out @@ -0,0 +1,285 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-create-insert2.out b/src/test/isolation/expected/ivm-create-insert2.out new file mode 100644 index 00000000000..907d892c6d4 --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert2.out @@ -0,0 +1,305 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + diff --git a/src/test/isolation/expected/ivm-create-insert3.out b/src/test/isolation/expected/ivm-create-insert3.out new file mode 100644 index 00000000000..907d892c6d4 --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert3.out @@ -0,0 +1,305 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert.out b/src/test/isolation/expected/ivm-insert-insert.out new file mode 100644 index 00000000000..5ca4cfea677 --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert.out @@ -0,0 +1,497 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; <waiting ...> +step c1: COMMIT; +step update2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; <waiting ...> +step c1: COMMIT; +step update2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; <waiting ...> +step c2: COMMIT; +step update1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; <waiting ...> +step c2: COMMIT; +step update1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); <waiting ...> +step c1: COMMIT; +step insert2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); <waiting ...> +step c1: COMMIT; +step insert2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); <waiting ...> +step c2: COMMIT; +step insert1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); <waiting ...> +step c2: COMMIT; +step insert1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert2.out b/src/test/isolation/expected/ivm-insert-insert2.out new file mode 100644 index 00000000000..e1c66d4de5e --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert2.out @@ -0,0 +1,373 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert3.out b/src/test/isolation/expected/ivm-insert-insert3.out new file mode 100644 index 00000000000..e1c66d4de5e --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert3.out @@ -0,0 +1,373 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert.out b/src/test/isolation/expected/ivm-refresh-insert.out new file mode 100644 index 00000000000..a925938bf1c --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert.out @@ -0,0 +1,213 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert2.out b/src/test/isolation/expected/ivm-refresh-insert2.out new file mode 100644 index 00000000000..dc1b16ae34e --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert2.out @@ -0,0 +1,191 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert3.out b/src/test/isolation/expected/ivm-refresh-insert3.out new file mode 100644 index 00000000000..dc1b16ae34e --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert3.out @@ -0,0 +1,191 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/isolation_schedule b/src/test/isolation/isolation_schedule index b8ebe92553c..6b7e873b370 100644 --- a/src/test/isolation/isolation_schedule +++ b/src/test/isolation/isolation_schedule @@ -128,3 +128,12 @@ test: matview-write-skew test: lock-nowait test: for-portion-of test: ddl-dependency-locking +test: ivm-create-insert +test: ivm-create-insert2 +test: ivm-create-insert3 +test: ivm-insert-insert +test: ivm-insert-insert2 +test: ivm-insert-insert3 +test: ivm-refresh-insert +test: ivm-refresh-insert2 +test: ivm-refresh-insert3 diff --git a/src/test/isolation/specs/ivm-create-insert.spec b/src/test/isolation/specs/ivm-create-insert.spec new file mode 100644 index 00000000000..ccd6fd080a9 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert.spec @@ -0,0 +1,47 @@ +# Test interaction between concurrent transactions performing +# create and insert in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-create-insert2.spec b/src/test/isolation/specs/ivm-create-insert2.spec new file mode 100644 index 00000000000..02cec85ae07 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert2.spec @@ -0,0 +1,54 @@ +# Test interaction between concurrent transactions performing +# create and insert in REPEATABLE READ isolation level +# +# Note: +# In this isolation level, it is possible that create_immv could +# create an inconsistent view not including effects of a concurrent +# transaction. So, an warning message is raised to suggest using it +# in READ COMMITTED or executing refresh_immv to make sure to +# make the view contents consistent. + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-create-insert3.spec b/src/test/isolation/specs/ivm-create-insert3.spec new file mode 100644 index 00000000000..19ce03185a4 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert3.spec @@ -0,0 +1,54 @@ +# Test interaction between concurrent transactions performing +# create and insert in SERIALIZABLE isolation level +# +# Note: +# In this isolation level, it is possible that create_immv could +# create an inconsistent view not including effects of a concurrent +# transaction. So, an warning message is raised to suggest using it +# in READ COMMITTED or executing refresh_immv to make sure to +# make the view contents consistent. + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert.spec b/src/test/isolation/specs/ivm-insert-insert.spec new file mode 100644 index 00000000000..b8f794ca191 --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert2.spec b/src/test/isolation/specs/ivm-insert-insert2.spec new file mode 100644 index 00000000000..ed086d1ba1e --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert2.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in REPEATABLE READ isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert3.spec b/src/test/isolation/specs/ivm-insert-insert3.spec new file mode 100644 index 00000000000..b18bd121033 --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert3.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in SERIALIZABLE isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert.spec b/src/test/isolation/specs/ivm-refresh-insert.spec new file mode 100644 index 00000000000..d7181251962 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert2.spec b/src/test/isolation/specs/ivm-refresh-insert2.spec new file mode 100644 index 00000000000..f2d1d5013f2 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert2.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in REPEATABLE READ isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert3.spec b/src/test/isolation/specs/ivm-refresh-insert3.spec new file mode 100644 index 00000000000..0ec2b1d1de0 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert3.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in SERIALIZABLE isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/regress/expected/incremental_matview.out b/src/test/regress/expected/incremental_matview.out new file mode 100644 index 00000000000..f215aa88e48 --- /dev/null +++ b/src/test/regress/expected/incremental_matview.out @@ -0,0 +1,1100 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ERROR: materialized view "mv_ivm_1" has not been populated +HINT: Use the REFRESH MATERIALIZED VIEW command. +REFRESH MATERIALIZED VIEW mv_ivm_1; +NOTICE: could not create an index on materialized view "mv_ivm_1" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 17 +(1 row) + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 1 +(1 row) + +ROLLBACK; +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_rename_index" on materialized view "mv_ivm_rename" +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +ERROR: IVM column can not be renamed +DROP MATERIALIZED VIEW mv_ivm_rename; +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_unique_index" on materialized view "mv_ivm_unique" +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +ERROR: unique index creation on IVM columns is not supported +DROP MATERIALIZED VIEW mv_ivm_unique; +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +NOTICE: could not create an index on materialized view "mv_ivm_func" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +NOTICE: could not create an index on materialized view "mv_ivm_no_tbl" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_duplicate" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +NOTICE: created index "mv_ivm_distinct_index" on materialized view "mv_ivm_distinct" +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 20 + 30 + 40 + 50 +(6 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +ROLLBACK; +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 120 | 2 | 60.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+---------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 220 | 2 | 110.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 20 | 1 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 120 | 2 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; + sum | count +-----+------- +(0 rows) + +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; + i | sum | count +---+-----+------- +(0 rows) + +ROLLBACK; +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 150 | 5 | 30.0000000000000000 +(1 row) + +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 210 | 6 | 35.0000000000000000 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +NOTICE: created index "mv_ivm_avg_bug_index" on materialized view "mv_ivm_avg_bug" +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 3 | 3.3333333333333333 + 2 | 80 | 3 | 26.6666666666666667 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_min_max_index" on materialized view "mv_ivm_min_max" +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 10 + 2 | 20 | 20 + 3 | 30 | 30 + 4 | 40 | 40 + 5 | 50 | 50 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 12 + 2 | 20 | 22 + 3 | 30 | 32 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 11 | 12 + 2 | 20 | 22 + 3 | 30 | 31 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min_max" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 50 +(1 row) + +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 0 | 70 +(1 row) + +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 60 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + | +(1 row) + +ROLLBACK; +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min; + min +----- + 10 +(1 row) + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + min +----- + 20 +(1 row) + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; + min +----- + 30 +(1 row) + +ROLLBACK; +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | sum +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | b +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ERROR: too many column names were specified +ROLLBACK; +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +NOTICE: could not create an index on materialized view "mv_self" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +----+---- + 10 | 10 + 20 | 20 + 30 | 30 +(3 rows) + +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 30 | 30 + 40 | 40 + 200 | 200 +(3 rows) + +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 130 | 130 + 300 | 300 +(4 rows) + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 70 | 70 + 70 | 77 + 77 | 70 + 77 | 77 + 130 | 130 + 300 | 300 +(8 rows) + +ROLLBACK; +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY v1; + v1 | v2 +----+----- + 10 | 100 + 20 | 200 + 30 | 300 +(3 rows) + +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv ORDER BY v1; + v1 | v2 +------+----- + 10 | 100 + 11 | 100 + 1020 | 200 + 1020 | 222 +(4 rows) + +ROLLBACK; +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +NOTICE: created index "mv_ri_index" on materialized view "mv_ri" +SELECT * FROM mv_ri ORDER BY i1; + i1 | i2 +----+---- + 1 | 1 + 2 | 2 + 3 | 3 +(3 rows) + +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; + i1 | i2 +----+---- + 3 | 3 + 10 | 10 +(2 rows) + +ROLLBACK; +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | +(2 rows) + +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | 20 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i +--- +(0 rows) + +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; + i +--- + 1 + +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 30 + | 3 +(2 rows) + +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 300 + | 30 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 1 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 4 +(1 row) + +ROLLBACK; +-- IMMV containing user defined type +BEGIN; +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: return type mytype is only a shell +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: argument type mytype is only a shell +LINE 1: CREATE FUNCTION mytype_out(mytype) + ^ +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +NOTICE: could not create an index on materialized view "mv_mytype" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + x +--- + 1 +(1 row) + +ROLLBACK; +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +ERROR: OUTER JOIN is not supported on incrementally maintainable materialized view +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +ERROR: CTE is not supported on incrementally maintainable materialized view +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +ERROR: ORDER BY clause is not supported on incrementally maintainable materialized view +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; +ERROR: HAVING clause is not supported on incrementally maintainable materialized view +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; +ERROR: mutable function is not supported on incrementally maintainable materialized view +HINT: functions must be marked IMMUTABLE +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; +ERROR: LIMIT/OFFSET clause is not supported on incrementally maintainable materialized view +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; +ERROR: DISTINCT ON is not supported on incrementally maintainable materialized view +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); +ERROR: TABLESAMPLE clause is not supported on incrementally maintainable materialized view +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; +ERROR: window functions are not supported on incrementally maintainable materialized view +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +ERROR: aggregate function with FILTER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +ERROR: aggregate function with DISTINCT arguments is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +ERROR: aggregate function with ORDER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); +ERROR: GROUPING SETS, ROLLUP, or CUBE clauses is not supported on incrementally maintainable materialized view +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ERROR: inheritance parent is not supported on incrementally maintainable materialized view +ROLLBACK; +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; +ERROR: UNION/INTERSECT/EXCEPT statements are not supported on incrementally maintainable materialized view +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; +ERROR: empty target list is not supported on incrementally maintainable materialized view +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; +ERROR: FOR UPDATE/SHARE clause is not supported on incrementally maintainable materialized view +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; +ERROR: column name __ivm_count__ is not supported on incrementally maintainable materialized view +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; +ERROR: GROUP BY expression not appearing in select list is not supported on incrementally maintainable materialized view +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); +ERROR: VALUES is not supported on incrementally maintainable materialized view +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +NOTICE: role "regress_ivm_admin" does not exist, skipping +DROP USER IF EXISTS regress_ivm_user; +NOTICE: role "regress_ivm_user" does not exist, skipping +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +NOTICE: could not create an index on materialized view "ivm_rls" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user +(1 row) + +RESET SESSION AUTHORIZATION; +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user + 3 | baz | regress_ivm_user +(2 rows) + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +-- +(1 row) + +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+-------+------------------ + 2 | bar | regress_ivm_user + 3 | baz | regress_ivm_user + 6 | corge | regress_ivm_user +(3 rows) + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +NOTICE: could not create an index on materialized view "ivm_rls2" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +RESET SESSION AUTHORIZATION; +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +-- +(1 row) + +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + id | data | owner | num +----+-------+------------------+--------- + 2 | bar | regress_ivm_user | two + 3 | baz_2 | regress_ivm_user | three_2 + 6 | corge | regress_ivm_user | six +(3 rows) + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +NOTICE: could not create an index on materialized view "mv_update_same" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + i +--- + 2 +(1 row) + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +NOTICE: created index "mv_self_ref_index" on materialized view "mv_self_ref" +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; + a | b +----+---- + 11 | + 12 | 11 + 13 | 12 +(3 rows) + +ROLLBACK; +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; +NOTICE: created index "mv_idx1_index" on materialized view "mv_idx1" +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; +NOTICE: created index "mv_idx2_index" on materialized view "mv_idx2" +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; +NOTICE: created index "mv_idx3_index" on materialized view "mv_idx3" +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +NOTICE: could not create an index on materialized view "mv_idx4" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; +NOTICE: could not create an index on materialized view "mv_idx5" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); +NOTICE: could not create an index on materialized view "mv_idx6" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ERROR: data type json has no default operator class for access method "btree" +ROLLBACK; +-- cleanup +DROP TABLE rls_tbl CASCADE; +NOTICE: drop cascades to 2 other objects +DETAIL: drop cascades to materialized view ivm_rls +drop cascades to materialized view ivm_rls2 +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; +DROP TABLE mv_base_b CASCADE; +NOTICE: drop cascades to 3 other objects +DETAIL: drop cascades to materialized view mv_ivm_1 +drop cascades to view b_view +drop cascades to materialized view b_mview +DROP TABLE mv_base_a CASCADE; diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index 8fa0a6c47fb..7caca5f64fd 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -77,6 +77,7 @@ test: brin_bloom brin_multi # Another group of parallel tests # ---------- test: create_table_like alter_generic alter_operator misc async dbsize merge misc_functions nls sysviews tsrf tid tidscan tidrangescan collate.utf8 collate.icu.utf8 incremental_sort create_role without_overlaps generated_virtual +test: incremental_matview # collate.linux.utf8 and collate.icu.utf8 tests cannot be run in parallel with each other # psql depends on create_am diff --git a/src/test/regress/sql/incremental_matview.sql b/src/test/regress/sql/incremental_matview.sql new file mode 100644 index 00000000000..2d55c393d6f --- /dev/null +++ b/src/test/regress/sql/incremental_matview.sql @@ -0,0 +1,580 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); + +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +REFRESH MATERIALIZED VIEW mv_ivm_1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; + +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; +ROLLBACK; + +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +DROP MATERIALIZED VIEW mv_ivm_rename; + +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +DROP MATERIALIZED VIEW mv_ivm_unique; + +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; + + +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +ROLLBACK; + +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +ROLLBACK; + +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +ROLLBACK; + +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +ROLLBACK; + +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +ROLLBACK; + +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min; + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); + +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; +ROLLBACK; + +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +SELECT * FROM mv_self ORDER BY v1; +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; +SELECT * FROM mv_self ORDER BY v1; + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + +ROLLBACK; + +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +SELECT * FROM mv ORDER BY v1; +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; +SELECT * FROM mv ORDER BY v1; +ROLLBACK; + +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +SELECT * FROM mv_ri ORDER BY i1; +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; +ROLLBACK; + +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +-- IMMV containing user defined type +BEGIN; + +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); + +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; + +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); + +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); + +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + +ROLLBACK; + +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; + +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; + +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; + +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; + +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; + +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); + +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; + +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); + +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ROLLBACK; + +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; + +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; + +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; + +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; + +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; + +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; + +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); + +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +DROP USER IF EXISTS regress_ivm_user; +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; + +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); + +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; + +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; + +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; +RESET SESSION AUTHORIZATION; + +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +RESET SESSION AUTHORIZATION; + +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; +ROLLBACK; + +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); + +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; + +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; + +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; + +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; + +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); + +ROLLBACK; + +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ROLLBACK; + +-- cleanup + +DROP TABLE rls_tbl CASCADE; +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; + +DROP TABLE mv_base_b CASCADE; +DROP TABLE mv_base_a CASCADE; -- 2.43.0 --Multipart=_Wed__1_Jul_2026_00_04_01_+0900_OVSy2WWK_9aByzDJ Content-Type: text/x-diff; name="v38-0009-Add-support-for-min-max-aggregates-for-IVM.patch" Content-Disposition: attachment; filename="v38-0009-Add-support-for-min-max-aggregates-for-IVM.patch" Content-Transfer-Encoding: 7bit ^ permalink raw reply [nested|flat] 78+ messages in thread
* [PATCH v37 10/11] Add regression tests for Incremental View Maintenance @ 2026-05-29 09:31 Yugo Nagata <[email protected]> 0 siblings, 0 replies; 78+ messages in thread From: Yugo Nagata @ 2026-05-29 09:31 UTC (permalink / raw) --- src/test/isolation/isolation_schedule | 9 + .../regress/expected/incremental_matview.out | 1100 +++++++++++++++++ src/test/regress/parallel_schedule | 1 + src/test/regress/sql/incremental_matview.sql | 580 +++++++++ 4 files changed, 1690 insertions(+) create mode 100644 src/test/regress/expected/incremental_matview.out create mode 100644 src/test/regress/sql/incremental_matview.sql diff --git a/src/test/isolation/isolation_schedule b/src/test/isolation/isolation_schedule index 15c33fad4c5..111fd465207 100644 --- a/src/test/isolation/isolation_schedule +++ b/src/test/isolation/isolation_schedule @@ -127,3 +127,12 @@ test: matview-write-skew test: lock-nowait test: for-portion-of test: ddl-dependency-locking +test: ivm-create-insert +test: ivm-create-insert2 +test: ivm-create-insert3 +test: ivm-insert-insert +test: ivm-insert-insert2 +test: ivm-insert-insert3 +test: ivm-refresh-insert +test: ivm-refresh-insert2 +test: ivm-refresh-insert3 diff --git a/src/test/regress/expected/incremental_matview.out b/src/test/regress/expected/incremental_matview.out new file mode 100644 index 00000000000..f215aa88e48 --- /dev/null +++ b/src/test/regress/expected/incremental_matview.out @@ -0,0 +1,1100 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ERROR: materialized view "mv_ivm_1" has not been populated +HINT: Use the REFRESH MATERIALIZED VIEW command. +REFRESH MATERIALIZED VIEW mv_ivm_1; +NOTICE: could not create an index on materialized view "mv_ivm_1" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 17 +(1 row) + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 1 +(1 row) + +ROLLBACK; +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_rename_index" on materialized view "mv_ivm_rename" +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +ERROR: IVM column can not be renamed +DROP MATERIALIZED VIEW mv_ivm_rename; +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_unique_index" on materialized view "mv_ivm_unique" +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +ERROR: unique index creation on IVM columns is not supported +DROP MATERIALIZED VIEW mv_ivm_unique; +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +NOTICE: could not create an index on materialized view "mv_ivm_func" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +NOTICE: could not create an index on materialized view "mv_ivm_no_tbl" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_duplicate" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +NOTICE: created index "mv_ivm_distinct_index" on materialized view "mv_ivm_distinct" +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 20 + 30 + 40 + 50 +(6 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +ROLLBACK; +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 120 | 2 | 60.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+---------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 220 | 2 | 110.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 20 | 1 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 120 | 2 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; + sum | count +-----+------- +(0 rows) + +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; + i | sum | count +---+-----+------- +(0 rows) + +ROLLBACK; +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 150 | 5 | 30.0000000000000000 +(1 row) + +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 210 | 6 | 35.0000000000000000 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +NOTICE: created index "mv_ivm_avg_bug_index" on materialized view "mv_ivm_avg_bug" +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 3 | 3.3333333333333333 + 2 | 80 | 3 | 26.6666666666666667 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_min_max_index" on materialized view "mv_ivm_min_max" +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 10 + 2 | 20 | 20 + 3 | 30 | 30 + 4 | 40 | 40 + 5 | 50 | 50 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 12 + 2 | 20 | 22 + 3 | 30 | 32 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 11 | 12 + 2 | 20 | 22 + 3 | 30 | 31 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min_max" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 50 +(1 row) + +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 0 | 70 +(1 row) + +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 60 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + | +(1 row) + +ROLLBACK; +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min; + min +----- + 10 +(1 row) + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + min +----- + 20 +(1 row) + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; + min +----- + 30 +(1 row) + +ROLLBACK; +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | sum +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | b +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ERROR: too many column names were specified +ROLLBACK; +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +NOTICE: could not create an index on materialized view "mv_self" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +----+---- + 10 | 10 + 20 | 20 + 30 | 30 +(3 rows) + +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 30 | 30 + 40 | 40 + 200 | 200 +(3 rows) + +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 130 | 130 + 300 | 300 +(4 rows) + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 70 | 70 + 70 | 77 + 77 | 70 + 77 | 77 + 130 | 130 + 300 | 300 +(8 rows) + +ROLLBACK; +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY v1; + v1 | v2 +----+----- + 10 | 100 + 20 | 200 + 30 | 300 +(3 rows) + +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv ORDER BY v1; + v1 | v2 +------+----- + 10 | 100 + 11 | 100 + 1020 | 200 + 1020 | 222 +(4 rows) + +ROLLBACK; +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +NOTICE: created index "mv_ri_index" on materialized view "mv_ri" +SELECT * FROM mv_ri ORDER BY i1; + i1 | i2 +----+---- + 1 | 1 + 2 | 2 + 3 | 3 +(3 rows) + +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; + i1 | i2 +----+---- + 3 | 3 + 10 | 10 +(2 rows) + +ROLLBACK; +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | +(2 rows) + +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | 20 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i +--- +(0 rows) + +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; + i +--- + 1 + +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 30 + | 3 +(2 rows) + +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 300 + | 30 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 1 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 4 +(1 row) + +ROLLBACK; +-- IMMV containing user defined type +BEGIN; +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: return type mytype is only a shell +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: argument type mytype is only a shell +LINE 1: CREATE FUNCTION mytype_out(mytype) + ^ +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +NOTICE: could not create an index on materialized view "mv_mytype" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + x +--- + 1 +(1 row) + +ROLLBACK; +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +ERROR: OUTER JOIN is not supported on incrementally maintainable materialized view +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +ERROR: CTE is not supported on incrementally maintainable materialized view +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +ERROR: ORDER BY clause is not supported on incrementally maintainable materialized view +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; +ERROR: HAVING clause is not supported on incrementally maintainable materialized view +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; +ERROR: mutable function is not supported on incrementally maintainable materialized view +HINT: functions must be marked IMMUTABLE +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; +ERROR: LIMIT/OFFSET clause is not supported on incrementally maintainable materialized view +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; +ERROR: DISTINCT ON is not supported on incrementally maintainable materialized view +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); +ERROR: TABLESAMPLE clause is not supported on incrementally maintainable materialized view +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; +ERROR: window functions are not supported on incrementally maintainable materialized view +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +ERROR: aggregate function with FILTER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +ERROR: aggregate function with DISTINCT arguments is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +ERROR: aggregate function with ORDER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); +ERROR: GROUPING SETS, ROLLUP, or CUBE clauses is not supported on incrementally maintainable materialized view +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ERROR: inheritance parent is not supported on incrementally maintainable materialized view +ROLLBACK; +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; +ERROR: UNION/INTERSECT/EXCEPT statements are not supported on incrementally maintainable materialized view +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; +ERROR: empty target list is not supported on incrementally maintainable materialized view +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; +ERROR: FOR UPDATE/SHARE clause is not supported on incrementally maintainable materialized view +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; +ERROR: column name __ivm_count__ is not supported on incrementally maintainable materialized view +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; +ERROR: GROUP BY expression not appearing in select list is not supported on incrementally maintainable materialized view +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); +ERROR: VALUES is not supported on incrementally maintainable materialized view +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +NOTICE: role "regress_ivm_admin" does not exist, skipping +DROP USER IF EXISTS regress_ivm_user; +NOTICE: role "regress_ivm_user" does not exist, skipping +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +NOTICE: could not create an index on materialized view "ivm_rls" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user +(1 row) + +RESET SESSION AUTHORIZATION; +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user + 3 | baz | regress_ivm_user +(2 rows) + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +-- +(1 row) + +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+-------+------------------ + 2 | bar | regress_ivm_user + 3 | baz | regress_ivm_user + 6 | corge | regress_ivm_user +(3 rows) + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +NOTICE: could not create an index on materialized view "ivm_rls2" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +RESET SESSION AUTHORIZATION; +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +-- +(1 row) + +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + id | data | owner | num +----+-------+------------------+--------- + 2 | bar | regress_ivm_user | two + 3 | baz_2 | regress_ivm_user | three_2 + 6 | corge | regress_ivm_user | six +(3 rows) + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +NOTICE: could not create an index on materialized view "mv_update_same" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + i +--- + 2 +(1 row) + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +NOTICE: created index "mv_self_ref_index" on materialized view "mv_self_ref" +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; + a | b +----+---- + 11 | + 12 | 11 + 13 | 12 +(3 rows) + +ROLLBACK; +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; +NOTICE: created index "mv_idx1_index" on materialized view "mv_idx1" +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; +NOTICE: created index "mv_idx2_index" on materialized view "mv_idx2" +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; +NOTICE: created index "mv_idx3_index" on materialized view "mv_idx3" +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +NOTICE: could not create an index on materialized view "mv_idx4" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; +NOTICE: could not create an index on materialized view "mv_idx5" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); +NOTICE: could not create an index on materialized view "mv_idx6" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ERROR: data type json has no default operator class for access method "btree" +ROLLBACK; +-- cleanup +DROP TABLE rls_tbl CASCADE; +NOTICE: drop cascades to 2 other objects +DETAIL: drop cascades to materialized view ivm_rls +drop cascades to materialized view ivm_rls2 +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; +DROP TABLE mv_base_b CASCADE; +NOTICE: drop cascades to 3 other objects +DETAIL: drop cascades to materialized view mv_ivm_1 +drop cascades to view b_view +drop cascades to materialized view b_mview +DROP TABLE mv_base_a CASCADE; diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index 8fa0a6c47fb..7caca5f64fd 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -77,6 +77,7 @@ test: brin_bloom brin_multi # Another group of parallel tests # ---------- test: create_table_like alter_generic alter_operator misc async dbsize merge misc_functions nls sysviews tsrf tid tidscan tidrangescan collate.utf8 collate.icu.utf8 incremental_sort create_role without_overlaps generated_virtual +test: incremental_matview # collate.linux.utf8 and collate.icu.utf8 tests cannot be run in parallel with each other # psql depends on create_am diff --git a/src/test/regress/sql/incremental_matview.sql b/src/test/regress/sql/incremental_matview.sql new file mode 100644 index 00000000000..2d55c393d6f --- /dev/null +++ b/src/test/regress/sql/incremental_matview.sql @@ -0,0 +1,580 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); + +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +REFRESH MATERIALIZED VIEW mv_ivm_1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; + +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; +ROLLBACK; + +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +DROP MATERIALIZED VIEW mv_ivm_rename; + +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +DROP MATERIALIZED VIEW mv_ivm_unique; + +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; + + +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +ROLLBACK; + +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +ROLLBACK; + +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +ROLLBACK; + +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +ROLLBACK; + +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +ROLLBACK; + +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min; + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); + +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; +ROLLBACK; + +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +SELECT * FROM mv_self ORDER BY v1; +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; +SELECT * FROM mv_self ORDER BY v1; + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + +ROLLBACK; + +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +SELECT * FROM mv ORDER BY v1; +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; +SELECT * FROM mv ORDER BY v1; +ROLLBACK; + +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +SELECT * FROM mv_ri ORDER BY i1; +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; +ROLLBACK; + +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +-- IMMV containing user defined type +BEGIN; + +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); + +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; + +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); + +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); + +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + +ROLLBACK; + +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; + +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; + +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; + +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; + +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; + +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); + +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; + +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); + +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ROLLBACK; + +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; + +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; + +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; + +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; + +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; + +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; + +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); + +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +DROP USER IF EXISTS regress_ivm_user; +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; + +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); + +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; + +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; + +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; +RESET SESSION AUTHORIZATION; + +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +RESET SESSION AUTHORIZATION; + +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; +ROLLBACK; + +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); + +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; + +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; + +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; + +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; + +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); + +ROLLBACK; + +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ROLLBACK; + +-- cleanup + +DROP TABLE rls_tbl CASCADE; +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; + +DROP TABLE mv_base_b CASCADE; +DROP TABLE mv_base_a CASCADE; -- 2.43.0 --Multipart=_Fri__29_May_2026_23_14_17_+0900_Te0o73X2VqYK57Gd Content-Type: text/x-diff; name="v37-0009-Add-support-for-min-max-aggregates-for-IVM.patch" Content-Disposition: attachment; filename="v37-0009-Add-support-for-min-max-aggregates-for-IVM.patch" Content-Transfer-Encoding: 7bit ^ permalink raw reply [nested|flat] 78+ messages in thread
* [PATCH v38 10/11] Add regression tests for Incremental View Maintenance @ 2026-05-29 09:31 Yugo Nagata <[email protected]> 0 siblings, 0 replies; 78+ messages in thread From: Yugo Nagata @ 2026-05-29 09:31 UTC (permalink / raw) --- .../isolation/expected/ivm-create-insert.out | 285 +++++ .../isolation/expected/ivm-create-insert2.out | 305 +++++ .../isolation/expected/ivm-create-insert3.out | 305 +++++ .../isolation/expected/ivm-insert-insert.out | 497 ++++++++ .../isolation/expected/ivm-insert-insert2.out | 373 ++++++ .../isolation/expected/ivm-insert-insert3.out | 373 ++++++ .../isolation/expected/ivm-refresh-insert.out | 213 ++++ .../expected/ivm-refresh-insert2.out | 191 +++ .../expected/ivm-refresh-insert3.out | 191 +++ src/test/isolation/isolation_schedule | 9 + .../isolation/specs/ivm-create-insert.spec | 47 + .../isolation/specs/ivm-create-insert2.spec | 54 + .../isolation/specs/ivm-create-insert3.spec | 54 + .../isolation/specs/ivm-insert-insert.spec | 62 + .../isolation/specs/ivm-insert-insert2.spec | 62 + .../isolation/specs/ivm-insert-insert3.spec | 62 + .../isolation/specs/ivm-refresh-insert.spec | 46 + .../isolation/specs/ivm-refresh-insert2.spec | 46 + .../isolation/specs/ivm-refresh-insert3.spec | 46 + .../regress/expected/incremental_matview.out | 1100 +++++++++++++++++ src/test/regress/parallel_schedule | 1 + src/test/regress/sql/incremental_matview.sql | 580 +++++++++ 22 files changed, 4902 insertions(+) create mode 100644 src/test/isolation/expected/ivm-create-insert.out create mode 100644 src/test/isolation/expected/ivm-create-insert2.out create mode 100644 src/test/isolation/expected/ivm-create-insert3.out create mode 100644 src/test/isolation/expected/ivm-insert-insert.out create mode 100644 src/test/isolation/expected/ivm-insert-insert2.out create mode 100644 src/test/isolation/expected/ivm-insert-insert3.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert2.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert3.out create mode 100644 src/test/isolation/specs/ivm-create-insert.spec create mode 100644 src/test/isolation/specs/ivm-create-insert2.spec create mode 100644 src/test/isolation/specs/ivm-create-insert3.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert2.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert3.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert2.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert3.spec create mode 100644 src/test/regress/expected/incremental_matview.out create mode 100644 src/test/regress/sql/incremental_matview.sql diff --git a/src/test/isolation/expected/ivm-create-insert.out b/src/test/isolation/expected/ivm-create-insert.out new file mode 100644 index 00000000000..5da00043aba --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert.out @@ -0,0 +1,285 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-create-insert2.out b/src/test/isolation/expected/ivm-create-insert2.out new file mode 100644 index 00000000000..907d892c6d4 --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert2.out @@ -0,0 +1,305 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + diff --git a/src/test/isolation/expected/ivm-create-insert3.out b/src/test/isolation/expected/ivm-create-insert3.out new file mode 100644 index 00000000000..907d892c6d4 --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert3.out @@ -0,0 +1,305 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert.out b/src/test/isolation/expected/ivm-insert-insert.out new file mode 100644 index 00000000000..5ca4cfea677 --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert.out @@ -0,0 +1,497 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; <waiting ...> +step c1: COMMIT; +step update2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; <waiting ...> +step c1: COMMIT; +step update2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; <waiting ...> +step c2: COMMIT; +step update1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; <waiting ...> +step c2: COMMIT; +step update1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); <waiting ...> +step c1: COMMIT; +step insert2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); <waiting ...> +step c1: COMMIT; +step insert2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); <waiting ...> +step c2: COMMIT; +step insert1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); <waiting ...> +step c2: COMMIT; +step insert1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert2.out b/src/test/isolation/expected/ivm-insert-insert2.out new file mode 100644 index 00000000000..e1c66d4de5e --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert2.out @@ -0,0 +1,373 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert3.out b/src/test/isolation/expected/ivm-insert-insert3.out new file mode 100644 index 00000000000..e1c66d4de5e --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert3.out @@ -0,0 +1,373 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert.out b/src/test/isolation/expected/ivm-refresh-insert.out new file mode 100644 index 00000000000..a925938bf1c --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert.out @@ -0,0 +1,213 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert2.out b/src/test/isolation/expected/ivm-refresh-insert2.out new file mode 100644 index 00000000000..dc1b16ae34e --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert2.out @@ -0,0 +1,191 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert3.out b/src/test/isolation/expected/ivm-refresh-insert3.out new file mode 100644 index 00000000000..dc1b16ae34e --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert3.out @@ -0,0 +1,191 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/isolation_schedule b/src/test/isolation/isolation_schedule index b8ebe92553c..6b7e873b370 100644 --- a/src/test/isolation/isolation_schedule +++ b/src/test/isolation/isolation_schedule @@ -128,3 +128,12 @@ test: matview-write-skew test: lock-nowait test: for-portion-of test: ddl-dependency-locking +test: ivm-create-insert +test: ivm-create-insert2 +test: ivm-create-insert3 +test: ivm-insert-insert +test: ivm-insert-insert2 +test: ivm-insert-insert3 +test: ivm-refresh-insert +test: ivm-refresh-insert2 +test: ivm-refresh-insert3 diff --git a/src/test/isolation/specs/ivm-create-insert.spec b/src/test/isolation/specs/ivm-create-insert.spec new file mode 100644 index 00000000000..ccd6fd080a9 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert.spec @@ -0,0 +1,47 @@ +# Test interaction between concurrent transactions performing +# create and insert in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-create-insert2.spec b/src/test/isolation/specs/ivm-create-insert2.spec new file mode 100644 index 00000000000..02cec85ae07 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert2.spec @@ -0,0 +1,54 @@ +# Test interaction between concurrent transactions performing +# create and insert in REPEATABLE READ isolation level +# +# Note: +# In this isolation level, it is possible that create_immv could +# create an inconsistent view not including effects of a concurrent +# transaction. So, an warning message is raised to suggest using it +# in READ COMMITTED or executing refresh_immv to make sure to +# make the view contents consistent. + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-create-insert3.spec b/src/test/isolation/specs/ivm-create-insert3.spec new file mode 100644 index 00000000000..19ce03185a4 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert3.spec @@ -0,0 +1,54 @@ +# Test interaction between concurrent transactions performing +# create and insert in SERIALIZABLE isolation level +# +# Note: +# In this isolation level, it is possible that create_immv could +# create an inconsistent view not including effects of a concurrent +# transaction. So, an warning message is raised to suggest using it +# in READ COMMITTED or executing refresh_immv to make sure to +# make the view contents consistent. + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert.spec b/src/test/isolation/specs/ivm-insert-insert.spec new file mode 100644 index 00000000000..b8f794ca191 --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert2.spec b/src/test/isolation/specs/ivm-insert-insert2.spec new file mode 100644 index 00000000000..ed086d1ba1e --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert2.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in REPEATABLE READ isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert3.spec b/src/test/isolation/specs/ivm-insert-insert3.spec new file mode 100644 index 00000000000..b18bd121033 --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert3.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in SERIALIZABLE isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert.spec b/src/test/isolation/specs/ivm-refresh-insert.spec new file mode 100644 index 00000000000..d7181251962 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert2.spec b/src/test/isolation/specs/ivm-refresh-insert2.spec new file mode 100644 index 00000000000..f2d1d5013f2 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert2.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in REPEATABLE READ isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert3.spec b/src/test/isolation/specs/ivm-refresh-insert3.spec new file mode 100644 index 00000000000..0ec2b1d1de0 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert3.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in SERIALIZABLE isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/regress/expected/incremental_matview.out b/src/test/regress/expected/incremental_matview.out new file mode 100644 index 00000000000..f215aa88e48 --- /dev/null +++ b/src/test/regress/expected/incremental_matview.out @@ -0,0 +1,1100 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ERROR: materialized view "mv_ivm_1" has not been populated +HINT: Use the REFRESH MATERIALIZED VIEW command. +REFRESH MATERIALIZED VIEW mv_ivm_1; +NOTICE: could not create an index on materialized view "mv_ivm_1" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 17 +(1 row) + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 1 +(1 row) + +ROLLBACK; +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_rename_index" on materialized view "mv_ivm_rename" +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +ERROR: IVM column can not be renamed +DROP MATERIALIZED VIEW mv_ivm_rename; +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_unique_index" on materialized view "mv_ivm_unique" +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +ERROR: unique index creation on IVM columns is not supported +DROP MATERIALIZED VIEW mv_ivm_unique; +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +NOTICE: could not create an index on materialized view "mv_ivm_func" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +NOTICE: could not create an index on materialized view "mv_ivm_no_tbl" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_duplicate" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +NOTICE: created index "mv_ivm_distinct_index" on materialized view "mv_ivm_distinct" +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 20 + 30 + 40 + 50 +(6 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +ROLLBACK; +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 120 | 2 | 60.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+---------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 220 | 2 | 110.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 20 | 1 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 120 | 2 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; + sum | count +-----+------- +(0 rows) + +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; + i | sum | count +---+-----+------- +(0 rows) + +ROLLBACK; +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 150 | 5 | 30.0000000000000000 +(1 row) + +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 210 | 6 | 35.0000000000000000 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +NOTICE: created index "mv_ivm_avg_bug_index" on materialized view "mv_ivm_avg_bug" +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 3 | 3.3333333333333333 + 2 | 80 | 3 | 26.6666666666666667 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_min_max_index" on materialized view "mv_ivm_min_max" +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 10 + 2 | 20 | 20 + 3 | 30 | 30 + 4 | 40 | 40 + 5 | 50 | 50 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 12 + 2 | 20 | 22 + 3 | 30 | 32 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 11 | 12 + 2 | 20 | 22 + 3 | 30 | 31 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min_max" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 50 +(1 row) + +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 0 | 70 +(1 row) + +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 60 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + | +(1 row) + +ROLLBACK; +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min; + min +----- + 10 +(1 row) + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + min +----- + 20 +(1 row) + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; + min +----- + 30 +(1 row) + +ROLLBACK; +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | sum +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | b +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ERROR: too many column names were specified +ROLLBACK; +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +NOTICE: could not create an index on materialized view "mv_self" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +----+---- + 10 | 10 + 20 | 20 + 30 | 30 +(3 rows) + +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 30 | 30 + 40 | 40 + 200 | 200 +(3 rows) + +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 130 | 130 + 300 | 300 +(4 rows) + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 70 | 70 + 70 | 77 + 77 | 70 + 77 | 77 + 130 | 130 + 300 | 300 +(8 rows) + +ROLLBACK; +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY v1; + v1 | v2 +----+----- + 10 | 100 + 20 | 200 + 30 | 300 +(3 rows) + +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv ORDER BY v1; + v1 | v2 +------+----- + 10 | 100 + 11 | 100 + 1020 | 200 + 1020 | 222 +(4 rows) + +ROLLBACK; +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +NOTICE: created index "mv_ri_index" on materialized view "mv_ri" +SELECT * FROM mv_ri ORDER BY i1; + i1 | i2 +----+---- + 1 | 1 + 2 | 2 + 3 | 3 +(3 rows) + +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; + i1 | i2 +----+---- + 3 | 3 + 10 | 10 +(2 rows) + +ROLLBACK; +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | +(2 rows) + +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | 20 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i +--- +(0 rows) + +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; + i +--- + 1 + +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 30 + | 3 +(2 rows) + +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 300 + | 30 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 1 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 4 +(1 row) + +ROLLBACK; +-- IMMV containing user defined type +BEGIN; +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: return type mytype is only a shell +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: argument type mytype is only a shell +LINE 1: CREATE FUNCTION mytype_out(mytype) + ^ +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +NOTICE: could not create an index on materialized view "mv_mytype" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + x +--- + 1 +(1 row) + +ROLLBACK; +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +ERROR: OUTER JOIN is not supported on incrementally maintainable materialized view +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +ERROR: CTE is not supported on incrementally maintainable materialized view +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +ERROR: ORDER BY clause is not supported on incrementally maintainable materialized view +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; +ERROR: HAVING clause is not supported on incrementally maintainable materialized view +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; +ERROR: mutable function is not supported on incrementally maintainable materialized view +HINT: functions must be marked IMMUTABLE +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; +ERROR: LIMIT/OFFSET clause is not supported on incrementally maintainable materialized view +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; +ERROR: DISTINCT ON is not supported on incrementally maintainable materialized view +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); +ERROR: TABLESAMPLE clause is not supported on incrementally maintainable materialized view +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; +ERROR: window functions are not supported on incrementally maintainable materialized view +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +ERROR: aggregate function with FILTER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +ERROR: aggregate function with DISTINCT arguments is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +ERROR: aggregate function with ORDER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); +ERROR: GROUPING SETS, ROLLUP, or CUBE clauses is not supported on incrementally maintainable materialized view +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ERROR: inheritance parent is not supported on incrementally maintainable materialized view +ROLLBACK; +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; +ERROR: UNION/INTERSECT/EXCEPT statements are not supported on incrementally maintainable materialized view +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; +ERROR: empty target list is not supported on incrementally maintainable materialized view +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; +ERROR: FOR UPDATE/SHARE clause is not supported on incrementally maintainable materialized view +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; +ERROR: column name __ivm_count__ is not supported on incrementally maintainable materialized view +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; +ERROR: GROUP BY expression not appearing in select list is not supported on incrementally maintainable materialized view +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); +ERROR: VALUES is not supported on incrementally maintainable materialized view +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +NOTICE: role "regress_ivm_admin" does not exist, skipping +DROP USER IF EXISTS regress_ivm_user; +NOTICE: role "regress_ivm_user" does not exist, skipping +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +NOTICE: could not create an index on materialized view "ivm_rls" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user +(1 row) + +RESET SESSION AUTHORIZATION; +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user + 3 | baz | regress_ivm_user +(2 rows) + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +-- +(1 row) + +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+-------+------------------ + 2 | bar | regress_ivm_user + 3 | baz | regress_ivm_user + 6 | corge | regress_ivm_user +(3 rows) + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +NOTICE: could not create an index on materialized view "ivm_rls2" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +RESET SESSION AUTHORIZATION; +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +-- +(1 row) + +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + id | data | owner | num +----+-------+------------------+--------- + 2 | bar | regress_ivm_user | two + 3 | baz_2 | regress_ivm_user | three_2 + 6 | corge | regress_ivm_user | six +(3 rows) + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +NOTICE: could not create an index on materialized view "mv_update_same" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + i +--- + 2 +(1 row) + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +NOTICE: created index "mv_self_ref_index" on materialized view "mv_self_ref" +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; + a | b +----+---- + 11 | + 12 | 11 + 13 | 12 +(3 rows) + +ROLLBACK; +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; +NOTICE: created index "mv_idx1_index" on materialized view "mv_idx1" +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; +NOTICE: created index "mv_idx2_index" on materialized view "mv_idx2" +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; +NOTICE: created index "mv_idx3_index" on materialized view "mv_idx3" +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +NOTICE: could not create an index on materialized view "mv_idx4" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; +NOTICE: could not create an index on materialized view "mv_idx5" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); +NOTICE: could not create an index on materialized view "mv_idx6" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ERROR: data type json has no default operator class for access method "btree" +ROLLBACK; +-- cleanup +DROP TABLE rls_tbl CASCADE; +NOTICE: drop cascades to 2 other objects +DETAIL: drop cascades to materialized view ivm_rls +drop cascades to materialized view ivm_rls2 +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; +DROP TABLE mv_base_b CASCADE; +NOTICE: drop cascades to 3 other objects +DETAIL: drop cascades to materialized view mv_ivm_1 +drop cascades to view b_view +drop cascades to materialized view b_mview +DROP TABLE mv_base_a CASCADE; diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index 8fa0a6c47fb..7caca5f64fd 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -77,6 +77,7 @@ test: brin_bloom brin_multi # Another group of parallel tests # ---------- test: create_table_like alter_generic alter_operator misc async dbsize merge misc_functions nls sysviews tsrf tid tidscan tidrangescan collate.utf8 collate.icu.utf8 incremental_sort create_role without_overlaps generated_virtual +test: incremental_matview # collate.linux.utf8 and collate.icu.utf8 tests cannot be run in parallel with each other # psql depends on create_am diff --git a/src/test/regress/sql/incremental_matview.sql b/src/test/regress/sql/incremental_matview.sql new file mode 100644 index 00000000000..2d55c393d6f --- /dev/null +++ b/src/test/regress/sql/incremental_matview.sql @@ -0,0 +1,580 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); + +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +REFRESH MATERIALIZED VIEW mv_ivm_1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; + +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; +ROLLBACK; + +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +DROP MATERIALIZED VIEW mv_ivm_rename; + +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +DROP MATERIALIZED VIEW mv_ivm_unique; + +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; + + +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +ROLLBACK; + +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +ROLLBACK; + +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +ROLLBACK; + +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +ROLLBACK; + +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +ROLLBACK; + +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min; + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); + +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; +ROLLBACK; + +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +SELECT * FROM mv_self ORDER BY v1; +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; +SELECT * FROM mv_self ORDER BY v1; + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + +ROLLBACK; + +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +SELECT * FROM mv ORDER BY v1; +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; +SELECT * FROM mv ORDER BY v1; +ROLLBACK; + +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +SELECT * FROM mv_ri ORDER BY i1; +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; +ROLLBACK; + +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +-- IMMV containing user defined type +BEGIN; + +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); + +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; + +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); + +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); + +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + +ROLLBACK; + +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; + +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; + +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; + +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; + +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; + +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); + +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; + +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); + +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ROLLBACK; + +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; + +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; + +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; + +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; + +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; + +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; + +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); + +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +DROP USER IF EXISTS regress_ivm_user; +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; + +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); + +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; + +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; + +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; +RESET SESSION AUTHORIZATION; + +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +RESET SESSION AUTHORIZATION; + +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; +ROLLBACK; + +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); + +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; + +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; + +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; + +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; + +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); + +ROLLBACK; + +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ROLLBACK; + +-- cleanup + +DROP TABLE rls_tbl CASCADE; +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; + +DROP TABLE mv_base_b CASCADE; +DROP TABLE mv_base_a CASCADE; -- 2.43.0 --Multipart=_Wed__1_Jul_2026_00_04_01_+0900_OVSy2WWK_9aByzDJ Content-Type: text/x-diff; name="v38-0009-Add-support-for-min-max-aggregates-for-IVM.patch" Content-Disposition: attachment; filename="v38-0009-Add-support-for-min-max-aggregates-for-IVM.patch" Content-Transfer-Encoding: 7bit ^ permalink raw reply [nested|flat] 78+ messages in thread
* [PATCH v39 7/8] Add regression tests for Incremental View Maintenance @ 2026-05-29 09:31 Yugo Nagata <[email protected]> 0 siblings, 0 replies; 78+ messages in thread From: Yugo Nagata @ 2026-05-29 09:31 UTC (permalink / raw) --- .../isolation/expected/ivm-create-insert.out | 285 ++++++++ .../isolation/expected/ivm-create-insert2.out | 305 ++++++++ .../isolation/expected/ivm-create-insert3.out | 305 ++++++++ .../isolation/expected/ivm-insert-insert.out | 497 +++++++++++++ .../isolation/expected/ivm-insert-insert2.out | 373 ++++++++++ .../isolation/expected/ivm-insert-insert3.out | 373 ++++++++++ .../isolation/expected/ivm-refresh-insert.out | 213 ++++++ .../expected/ivm-refresh-insert2.out | 191 +++++ .../expected/ivm-refresh-insert3.out | 191 +++++ src/test/isolation/isolation_schedule | 9 + .../isolation/specs/ivm-create-insert.spec | 47 ++ .../isolation/specs/ivm-create-insert2.spec | 54 ++ .../isolation/specs/ivm-create-insert3.spec | 54 ++ .../isolation/specs/ivm-insert-insert.spec | 62 ++ .../isolation/specs/ivm-insert-insert2.spec | 62 ++ .../isolation/specs/ivm-insert-insert3.spec | 62 ++ .../isolation/specs/ivm-refresh-insert.spec | 46 ++ .../isolation/specs/ivm-refresh-insert2.spec | 46 ++ .../isolation/specs/ivm-refresh-insert3.spec | 46 ++ .../regress/expected/incremental_matview.out | 667 ++++++++++++++++++ src/test/regress/parallel_schedule | 1 + src/test/regress/sql/incremental_matview.sql | 407 +++++++++++ 22 files changed, 4296 insertions(+) create mode 100644 src/test/isolation/expected/ivm-create-insert.out create mode 100644 src/test/isolation/expected/ivm-create-insert2.out create mode 100644 src/test/isolation/expected/ivm-create-insert3.out create mode 100644 src/test/isolation/expected/ivm-insert-insert.out create mode 100644 src/test/isolation/expected/ivm-insert-insert2.out create mode 100644 src/test/isolation/expected/ivm-insert-insert3.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert2.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert3.out create mode 100644 src/test/isolation/specs/ivm-create-insert.spec create mode 100644 src/test/isolation/specs/ivm-create-insert2.spec create mode 100644 src/test/isolation/specs/ivm-create-insert3.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert2.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert3.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert2.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert3.spec create mode 100644 src/test/regress/expected/incremental_matview.out create mode 100644 src/test/regress/sql/incremental_matview.sql diff --git a/src/test/isolation/expected/ivm-create-insert.out b/src/test/isolation/expected/ivm-create-insert.out new file mode 100644 index 00000000000..5da00043aba --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert.out @@ -0,0 +1,285 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-create-insert2.out b/src/test/isolation/expected/ivm-create-insert2.out new file mode 100644 index 00000000000..907d892c6d4 --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert2.out @@ -0,0 +1,305 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + diff --git a/src/test/isolation/expected/ivm-create-insert3.out b/src/test/isolation/expected/ivm-create-insert3.out new file mode 100644 index 00000000000..907d892c6d4 --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert3.out @@ -0,0 +1,305 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert.out b/src/test/isolation/expected/ivm-insert-insert.out new file mode 100644 index 00000000000..5ca4cfea677 --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert.out @@ -0,0 +1,497 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; <waiting ...> +step c1: COMMIT; +step update2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; <waiting ...> +step c1: COMMIT; +step update2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; <waiting ...> +step c2: COMMIT; +step update1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; <waiting ...> +step c2: COMMIT; +step update1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); <waiting ...> +step c1: COMMIT; +step insert2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); <waiting ...> +step c1: COMMIT; +step insert2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); <waiting ...> +step c2: COMMIT; +step insert1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); <waiting ...> +step c2: COMMIT; +step insert1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert2.out b/src/test/isolation/expected/ivm-insert-insert2.out new file mode 100644 index 00000000000..e1c66d4de5e --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert2.out @@ -0,0 +1,373 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert3.out b/src/test/isolation/expected/ivm-insert-insert3.out new file mode 100644 index 00000000000..e1c66d4de5e --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert3.out @@ -0,0 +1,373 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert.out b/src/test/isolation/expected/ivm-refresh-insert.out new file mode 100644 index 00000000000..a925938bf1c --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert.out @@ -0,0 +1,213 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert2.out b/src/test/isolation/expected/ivm-refresh-insert2.out new file mode 100644 index 00000000000..dc1b16ae34e --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert2.out @@ -0,0 +1,191 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert3.out b/src/test/isolation/expected/ivm-refresh-insert3.out new file mode 100644 index 00000000000..dc1b16ae34e --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert3.out @@ -0,0 +1,191 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/isolation_schedule b/src/test/isolation/isolation_schedule index b8ebe92553c..6b7e873b370 100644 --- a/src/test/isolation/isolation_schedule +++ b/src/test/isolation/isolation_schedule @@ -128,3 +128,12 @@ test: matview-write-skew test: lock-nowait test: for-portion-of test: ddl-dependency-locking +test: ivm-create-insert +test: ivm-create-insert2 +test: ivm-create-insert3 +test: ivm-insert-insert +test: ivm-insert-insert2 +test: ivm-insert-insert3 +test: ivm-refresh-insert +test: ivm-refresh-insert2 +test: ivm-refresh-insert3 diff --git a/src/test/isolation/specs/ivm-create-insert.spec b/src/test/isolation/specs/ivm-create-insert.spec new file mode 100644 index 00000000000..ccd6fd080a9 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert.spec @@ -0,0 +1,47 @@ +# Test interaction between concurrent transactions performing +# create and insert in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-create-insert2.spec b/src/test/isolation/specs/ivm-create-insert2.spec new file mode 100644 index 00000000000..02cec85ae07 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert2.spec @@ -0,0 +1,54 @@ +# Test interaction between concurrent transactions performing +# create and insert in REPEATABLE READ isolation level +# +# Note: +# In this isolation level, it is possible that create_immv could +# create an inconsistent view not including effects of a concurrent +# transaction. So, an warning message is raised to suggest using it +# in READ COMMITTED or executing refresh_immv to make sure to +# make the view contents consistent. + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-create-insert3.spec b/src/test/isolation/specs/ivm-create-insert3.spec new file mode 100644 index 00000000000..19ce03185a4 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert3.spec @@ -0,0 +1,54 @@ +# Test interaction between concurrent transactions performing +# create and insert in SERIALIZABLE isolation level +# +# Note: +# In this isolation level, it is possible that create_immv could +# create an inconsistent view not including effects of a concurrent +# transaction. So, an warning message is raised to suggest using it +# in READ COMMITTED or executing refresh_immv to make sure to +# make the view contents consistent. + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert.spec b/src/test/isolation/specs/ivm-insert-insert.spec new file mode 100644 index 00000000000..b8f794ca191 --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert2.spec b/src/test/isolation/specs/ivm-insert-insert2.spec new file mode 100644 index 00000000000..ed086d1ba1e --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert2.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in REPEATABLE READ isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert3.spec b/src/test/isolation/specs/ivm-insert-insert3.spec new file mode 100644 index 00000000000..b18bd121033 --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert3.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in SERIALIZABLE isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert.spec b/src/test/isolation/specs/ivm-refresh-insert.spec new file mode 100644 index 00000000000..d7181251962 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert2.spec b/src/test/isolation/specs/ivm-refresh-insert2.spec new file mode 100644 index 00000000000..f2d1d5013f2 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert2.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in REPEATABLE READ isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert3.spec b/src/test/isolation/specs/ivm-refresh-insert3.spec new file mode 100644 index 00000000000..0ec2b1d1de0 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert3.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in SERIALIZABLE isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/regress/expected/incremental_matview.out b/src/test/regress/expected/incremental_matview.out new file mode 100644 index 00000000000..c7fd19fdca3 --- /dev/null +++ b/src/test/regress/expected/incremental_matview.out @@ -0,0 +1,667 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ERROR: materialized view "mv_ivm_1" has not been populated +HINT: Use the REFRESH MATERIALIZED VIEW command. +REFRESH MATERIALIZED VIEW mv_ivm_1; +NOTICE: could not create an index on materialized view "mv_ivm_1" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 17 +(1 row) + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 1 +(1 row) + +ROLLBACK; +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- DISTINCT not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT * FROM mv_base_a; +ERROR: DISTINCT is not supported on incrementally maintainable materialized view +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +NOTICE: could not create an index on materialized view "mv_ivm_func" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +NOTICE: could not create an index on materialized view "mv_ivm_no_tbl" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- result of materialized view have duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_duplicate" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 20 + 30 + 40 + 50 +(6 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +ROLLBACK; +-- aggregate not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +ERROR: aggregate function is not supported on incrementally maintainable materialized view +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +NOTICE: could not create an index on materialized view "mv_self" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +----+---- + 10 | 10 + 20 | 20 + 30 | 30 +(3 rows) + +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 30 | 30 + 40 | 40 + 200 | 200 +(3 rows) + +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 130 | 130 + 300 | 300 +(4 rows) + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 70 | 70 + 70 | 77 + 77 | 70 + 77 | 77 + 130 | 130 + 300 | 300 +(8 rows) + +ROLLBACK; +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY v1; + v1 | v2 +----+----- + 10 | 100 + 20 | 200 + 30 | 300 +(3 rows) + +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv ORDER BY v1; + v1 | v2 +------+----- + 10 | 100 + 11 | 100 + 1020 | 200 + 1020 | 222 +(4 rows) + +ROLLBACK; +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +NOTICE: created index "mv_ri_index" on materialized view "mv_ri" +SELECT * FROM mv_ri ORDER BY i1; + i1 | i2 +----+---- + 1 | 1 + 2 | 2 + 3 | 3 +(3 rows) + +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; + i1 | i2 +----+---- + 3 | 3 + 10 | 10 +(2 rows) + +ROLLBACK; +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | +(2 rows) + +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | 20 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i +--- +(0 rows) + +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; + i +--- + 1 + +(2 rows) + +ROLLBACK; +-- IMMV containing user defined type +BEGIN; +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: return type mytype is only a shell +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: argument type mytype is only a shell +LINE 1: CREATE FUNCTION mytype_out(mytype) + ^ +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +NOTICE: could not create an index on materialized view "mv_mytype" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + x +--- + 1 +(1 row) + +ROLLBACK; +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +ERROR: OUTER JOIN is not supported on incrementally maintainable materialized view +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +ERROR: CTE is not supported on incrementally maintainable materialized view +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +ERROR: ORDER BY clause is not supported on incrementally maintainable materialized view +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; +ERROR: HAVING clause is not supported on incrementally maintainable materialized view +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; +ERROR: mutable function is not supported on incrementally maintainable materialized view +HINT: functions must be marked IMMUTABLE +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; +ERROR: LIMIT/OFFSET clause is not supported on incrementally maintainable materialized view +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; +ERROR: DISTINCT is not supported on incrementally maintainable materialized view +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); +ERROR: TABLESAMPLE clause is not supported on incrementally maintainable materialized view +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; +ERROR: window functions are not supported on incrementally maintainable materialized view +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ERROR: inheritance parent is not supported on incrementally maintainable materialized view +ROLLBACK; +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; +ERROR: UNION/INTERSECT/EXCEPT statements are not supported on incrementally maintainable materialized view +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; +ERROR: empty target list is not supported on incrementally maintainable materialized view +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; +ERROR: FOR UPDATE/SHARE clause is not supported on incrementally maintainable materialized view +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; +ERROR: column name __ivm_count__ is not supported on incrementally maintainable materialized view +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; +ERROR: aggregate function is not supported on incrementally maintainable materialized view +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); +ERROR: VALUES is not supported on incrementally maintainable materialized view +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +NOTICE: role "regress_ivm_admin" does not exist, skipping +DROP USER IF EXISTS regress_ivm_user; +NOTICE: role "regress_ivm_user" does not exist, skipping +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +NOTICE: could not create an index on materialized view "ivm_rls" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user +(1 row) + +RESET SESSION AUTHORIZATION; +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user + 3 | baz | regress_ivm_user +(2 rows) + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +-- +(1 row) + +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+-------+------------------ + 2 | bar | regress_ivm_user + 3 | baz | regress_ivm_user + 6 | corge | regress_ivm_user +(3 rows) + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +NOTICE: could not create an index on materialized view "ivm_rls2" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +RESET SESSION AUTHORIZATION; +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +-- +(1 row) + +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + id | data | owner | num +----+-------+------------------+--------- + 2 | bar | regress_ivm_user | two + 3 | baz_2 | regress_ivm_user | three_2 + 6 | corge | regress_ivm_user | six +(3 rows) + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +NOTICE: could not create an index on materialized view "mv_update_same" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + i +--- + 2 +(1 row) + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +NOTICE: created index "mv_self_ref_index" on materialized view "mv_self_ref" +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; + a | b +----+---- + 11 | + 12 | 11 + 13 | 12 +(3 rows) + +ROLLBACK; +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; +NOTICE: created index "mv_idx3_index" on materialized view "mv_idx3" +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +NOTICE: could not create an index on materialized view "mv_idx4" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; +NOTICE: could not create an index on materialized view "mv_idx5" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); +NOTICE: could not create an index on materialized view "mv_idx6" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ERROR: data type json has no default operator class for access method "btree" +ROLLBACK; +-- cleanup +DROP TABLE rls_tbl CASCADE; +NOTICE: drop cascades to 2 other objects +DETAIL: drop cascades to materialized view ivm_rls +drop cascades to materialized view ivm_rls2 +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; +DROP TABLE mv_base_b CASCADE; +NOTICE: drop cascades to 3 other objects +DETAIL: drop cascades to materialized view mv_ivm_1 +drop cascades to view b_view +drop cascades to materialized view b_mview +DROP TABLE mv_base_a CASCADE; diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index 8fa0a6c47fb..7caca5f64fd 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -77,6 +77,7 @@ test: brin_bloom brin_multi # Another group of parallel tests # ---------- test: create_table_like alter_generic alter_operator misc async dbsize merge misc_functions nls sysviews tsrf tid tidscan tidrangescan collate.utf8 collate.icu.utf8 incremental_sort create_role without_overlaps generated_virtual +test: incremental_matview # collate.linux.utf8 and collate.icu.utf8 tests cannot be run in parallel with each other # psql depends on create_am diff --git a/src/test/regress/sql/incremental_matview.sql b/src/test/regress/sql/incremental_matview.sql new file mode 100644 index 00000000000..7313ad82f3e --- /dev/null +++ b/src/test/regress/sql/incremental_matview.sql @@ -0,0 +1,407 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); + +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +REFRESH MATERIALIZED VIEW mv_ivm_1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; + +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; +ROLLBACK; + +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- DISTINCT not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT * FROM mv_base_a; + +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; + + +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +ROLLBACK; + +-- result of materialized view have duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +ROLLBACK; + +-- aggregate not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; + +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +SELECT * FROM mv_self ORDER BY v1; +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; +SELECT * FROM mv_self ORDER BY v1; + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + +ROLLBACK; + +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +SELECT * FROM mv ORDER BY v1; +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; +SELECT * FROM mv ORDER BY v1; +ROLLBACK; + +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +SELECT * FROM mv_ri ORDER BY i1; +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; +ROLLBACK; + +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +-- IMMV containing user defined type +BEGIN; + +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); + +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; + +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); + +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); + +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + +ROLLBACK; + +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; + +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; + +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; + +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; + +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; + +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); + +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; + +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ROLLBACK; + +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; + +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; + +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; + +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; + +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; + +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); + +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +DROP USER IF EXISTS regress_ivm_user; +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; + +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); + +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; + +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; + +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; +RESET SESSION AUTHORIZATION; + +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +RESET SESSION AUTHORIZATION; + +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; +ROLLBACK; + +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); + +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; + +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; + +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); + +ROLLBACK; + +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ROLLBACK; + +-- cleanup + +DROP TABLE rls_tbl CASCADE; +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; + +DROP TABLE mv_base_b CASCADE; +DROP TABLE mv_base_a CASCADE; -- 2.43.0 --Multipart=_Fri__3_Jul_2026_19_11_16_+0900_CskxSIu_iGcDMEyM Content-Type: text/x-diff; name="v39-0006-Add-Incremental-View-Maintenance-support.patch" Content-Disposition: attachment; filename="v39-0006-Add-Incremental-View-Maintenance-support.patch" Content-Transfer-Encoding: 7bit ^ permalink raw reply [nested|flat] 78+ messages in thread
* [PATCH v37 10/11] Add regression tests for Incremental View Maintenance @ 2026-05-29 09:31 Yugo Nagata <[email protected]> 0 siblings, 0 replies; 78+ messages in thread From: Yugo Nagata @ 2026-05-29 09:31 UTC (permalink / raw) --- src/test/isolation/isolation_schedule | 9 + .../regress/expected/incremental_matview.out | 1100 +++++++++++++++++ src/test/regress/parallel_schedule | 1 + src/test/regress/sql/incremental_matview.sql | 580 +++++++++ 4 files changed, 1690 insertions(+) create mode 100644 src/test/regress/expected/incremental_matview.out create mode 100644 src/test/regress/sql/incremental_matview.sql diff --git a/src/test/isolation/isolation_schedule b/src/test/isolation/isolation_schedule index 15c33fad4c5..111fd465207 100644 --- a/src/test/isolation/isolation_schedule +++ b/src/test/isolation/isolation_schedule @@ -127,3 +127,12 @@ test: matview-write-skew test: lock-nowait test: for-portion-of test: ddl-dependency-locking +test: ivm-create-insert +test: ivm-create-insert2 +test: ivm-create-insert3 +test: ivm-insert-insert +test: ivm-insert-insert2 +test: ivm-insert-insert3 +test: ivm-refresh-insert +test: ivm-refresh-insert2 +test: ivm-refresh-insert3 diff --git a/src/test/regress/expected/incremental_matview.out b/src/test/regress/expected/incremental_matview.out new file mode 100644 index 00000000000..f215aa88e48 --- /dev/null +++ b/src/test/regress/expected/incremental_matview.out @@ -0,0 +1,1100 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ERROR: materialized view "mv_ivm_1" has not been populated +HINT: Use the REFRESH MATERIALIZED VIEW command. +REFRESH MATERIALIZED VIEW mv_ivm_1; +NOTICE: could not create an index on materialized view "mv_ivm_1" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 17 +(1 row) + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 1 +(1 row) + +ROLLBACK; +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_rename_index" on materialized view "mv_ivm_rename" +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +ERROR: IVM column can not be renamed +DROP MATERIALIZED VIEW mv_ivm_rename; +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_unique_index" on materialized view "mv_ivm_unique" +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +ERROR: unique index creation on IVM columns is not supported +DROP MATERIALIZED VIEW mv_ivm_unique; +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +NOTICE: could not create an index on materialized view "mv_ivm_func" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +NOTICE: could not create an index on materialized view "mv_ivm_no_tbl" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_duplicate" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +NOTICE: created index "mv_ivm_distinct_index" on materialized view "mv_ivm_distinct" +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 20 + 30 + 40 + 50 +(6 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +ROLLBACK; +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 120 | 2 | 60.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+---------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 220 | 2 | 110.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 20 | 1 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 120 | 2 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; + sum | count +-----+------- +(0 rows) + +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; + i | sum | count +---+-----+------- +(0 rows) + +ROLLBACK; +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 150 | 5 | 30.0000000000000000 +(1 row) + +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 210 | 6 | 35.0000000000000000 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +NOTICE: created index "mv_ivm_avg_bug_index" on materialized view "mv_ivm_avg_bug" +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 3 | 3.3333333333333333 + 2 | 80 | 3 | 26.6666666666666667 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_min_max_index" on materialized view "mv_ivm_min_max" +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 10 + 2 | 20 | 20 + 3 | 30 | 30 + 4 | 40 | 40 + 5 | 50 | 50 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 12 + 2 | 20 | 22 + 3 | 30 | 32 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 11 | 12 + 2 | 20 | 22 + 3 | 30 | 31 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min_max" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 50 +(1 row) + +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 0 | 70 +(1 row) + +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 60 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + | +(1 row) + +ROLLBACK; +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min; + min +----- + 10 +(1 row) + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + min +----- + 20 +(1 row) + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; + min +----- + 30 +(1 row) + +ROLLBACK; +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | sum +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | b +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ERROR: too many column names were specified +ROLLBACK; +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +NOTICE: could not create an index on materialized view "mv_self" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +----+---- + 10 | 10 + 20 | 20 + 30 | 30 +(3 rows) + +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 30 | 30 + 40 | 40 + 200 | 200 +(3 rows) + +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 130 | 130 + 300 | 300 +(4 rows) + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 70 | 70 + 70 | 77 + 77 | 70 + 77 | 77 + 130 | 130 + 300 | 300 +(8 rows) + +ROLLBACK; +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY v1; + v1 | v2 +----+----- + 10 | 100 + 20 | 200 + 30 | 300 +(3 rows) + +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv ORDER BY v1; + v1 | v2 +------+----- + 10 | 100 + 11 | 100 + 1020 | 200 + 1020 | 222 +(4 rows) + +ROLLBACK; +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +NOTICE: created index "mv_ri_index" on materialized view "mv_ri" +SELECT * FROM mv_ri ORDER BY i1; + i1 | i2 +----+---- + 1 | 1 + 2 | 2 + 3 | 3 +(3 rows) + +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; + i1 | i2 +----+---- + 3 | 3 + 10 | 10 +(2 rows) + +ROLLBACK; +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | +(2 rows) + +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | 20 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i +--- +(0 rows) + +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; + i +--- + 1 + +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 30 + | 3 +(2 rows) + +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 300 + | 30 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 1 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 4 +(1 row) + +ROLLBACK; +-- IMMV containing user defined type +BEGIN; +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: return type mytype is only a shell +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: argument type mytype is only a shell +LINE 1: CREATE FUNCTION mytype_out(mytype) + ^ +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +NOTICE: could not create an index on materialized view "mv_mytype" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + x +--- + 1 +(1 row) + +ROLLBACK; +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +ERROR: OUTER JOIN is not supported on incrementally maintainable materialized view +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +ERROR: CTE is not supported on incrementally maintainable materialized view +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +ERROR: ORDER BY clause is not supported on incrementally maintainable materialized view +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; +ERROR: HAVING clause is not supported on incrementally maintainable materialized view +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; +ERROR: mutable function is not supported on incrementally maintainable materialized view +HINT: functions must be marked IMMUTABLE +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; +ERROR: LIMIT/OFFSET clause is not supported on incrementally maintainable materialized view +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; +ERROR: DISTINCT ON is not supported on incrementally maintainable materialized view +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); +ERROR: TABLESAMPLE clause is not supported on incrementally maintainable materialized view +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; +ERROR: window functions are not supported on incrementally maintainable materialized view +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +ERROR: aggregate function with FILTER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +ERROR: aggregate function with DISTINCT arguments is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +ERROR: aggregate function with ORDER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); +ERROR: GROUPING SETS, ROLLUP, or CUBE clauses is not supported on incrementally maintainable materialized view +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ERROR: inheritance parent is not supported on incrementally maintainable materialized view +ROLLBACK; +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; +ERROR: UNION/INTERSECT/EXCEPT statements are not supported on incrementally maintainable materialized view +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; +ERROR: empty target list is not supported on incrementally maintainable materialized view +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; +ERROR: FOR UPDATE/SHARE clause is not supported on incrementally maintainable materialized view +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; +ERROR: column name __ivm_count__ is not supported on incrementally maintainable materialized view +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; +ERROR: GROUP BY expression not appearing in select list is not supported on incrementally maintainable materialized view +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); +ERROR: VALUES is not supported on incrementally maintainable materialized view +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +NOTICE: role "regress_ivm_admin" does not exist, skipping +DROP USER IF EXISTS regress_ivm_user; +NOTICE: role "regress_ivm_user" does not exist, skipping +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +NOTICE: could not create an index on materialized view "ivm_rls" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user +(1 row) + +RESET SESSION AUTHORIZATION; +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user + 3 | baz | regress_ivm_user +(2 rows) + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +-- +(1 row) + +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+-------+------------------ + 2 | bar | regress_ivm_user + 3 | baz | regress_ivm_user + 6 | corge | regress_ivm_user +(3 rows) + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +NOTICE: could not create an index on materialized view "ivm_rls2" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +RESET SESSION AUTHORIZATION; +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +-- +(1 row) + +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + id | data | owner | num +----+-------+------------------+--------- + 2 | bar | regress_ivm_user | two + 3 | baz_2 | regress_ivm_user | three_2 + 6 | corge | regress_ivm_user | six +(3 rows) + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +NOTICE: could not create an index on materialized view "mv_update_same" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + i +--- + 2 +(1 row) + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +NOTICE: created index "mv_self_ref_index" on materialized view "mv_self_ref" +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; + a | b +----+---- + 11 | + 12 | 11 + 13 | 12 +(3 rows) + +ROLLBACK; +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; +NOTICE: created index "mv_idx1_index" on materialized view "mv_idx1" +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; +NOTICE: created index "mv_idx2_index" on materialized view "mv_idx2" +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; +NOTICE: created index "mv_idx3_index" on materialized view "mv_idx3" +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +NOTICE: could not create an index on materialized view "mv_idx4" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; +NOTICE: could not create an index on materialized view "mv_idx5" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); +NOTICE: could not create an index on materialized view "mv_idx6" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ERROR: data type json has no default operator class for access method "btree" +ROLLBACK; +-- cleanup +DROP TABLE rls_tbl CASCADE; +NOTICE: drop cascades to 2 other objects +DETAIL: drop cascades to materialized view ivm_rls +drop cascades to materialized view ivm_rls2 +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; +DROP TABLE mv_base_b CASCADE; +NOTICE: drop cascades to 3 other objects +DETAIL: drop cascades to materialized view mv_ivm_1 +drop cascades to view b_view +drop cascades to materialized view b_mview +DROP TABLE mv_base_a CASCADE; diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index 8fa0a6c47fb..7caca5f64fd 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -77,6 +77,7 @@ test: brin_bloom brin_multi # Another group of parallel tests # ---------- test: create_table_like alter_generic alter_operator misc async dbsize merge misc_functions nls sysviews tsrf tid tidscan tidrangescan collate.utf8 collate.icu.utf8 incremental_sort create_role without_overlaps generated_virtual +test: incremental_matview # collate.linux.utf8 and collate.icu.utf8 tests cannot be run in parallel with each other # psql depends on create_am diff --git a/src/test/regress/sql/incremental_matview.sql b/src/test/regress/sql/incremental_matview.sql new file mode 100644 index 00000000000..2d55c393d6f --- /dev/null +++ b/src/test/regress/sql/incremental_matview.sql @@ -0,0 +1,580 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); + +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +REFRESH MATERIALIZED VIEW mv_ivm_1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; + +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; +ROLLBACK; + +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +DROP MATERIALIZED VIEW mv_ivm_rename; + +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +DROP MATERIALIZED VIEW mv_ivm_unique; + +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; + + +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +ROLLBACK; + +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +ROLLBACK; + +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +ROLLBACK; + +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +ROLLBACK; + +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +ROLLBACK; + +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min; + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); + +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; +ROLLBACK; + +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +SELECT * FROM mv_self ORDER BY v1; +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; +SELECT * FROM mv_self ORDER BY v1; + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + +ROLLBACK; + +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +SELECT * FROM mv ORDER BY v1; +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; +SELECT * FROM mv ORDER BY v1; +ROLLBACK; + +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +SELECT * FROM mv_ri ORDER BY i1; +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; +ROLLBACK; + +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +-- IMMV containing user defined type +BEGIN; + +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); + +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; + +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); + +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); + +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + +ROLLBACK; + +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; + +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; + +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; + +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; + +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; + +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); + +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; + +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); + +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ROLLBACK; + +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; + +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; + +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; + +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; + +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; + +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; + +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); + +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +DROP USER IF EXISTS regress_ivm_user; +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; + +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); + +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; + +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; + +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; +RESET SESSION AUTHORIZATION; + +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +RESET SESSION AUTHORIZATION; + +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; +ROLLBACK; + +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); + +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; + +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; + +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; + +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; + +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); + +ROLLBACK; + +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ROLLBACK; + +-- cleanup + +DROP TABLE rls_tbl CASCADE; +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; + +DROP TABLE mv_base_b CASCADE; +DROP TABLE mv_base_a CASCADE; -- 2.43.0 --Multipart=_Fri__29_May_2026_23_14_17_+0900_Te0o73X2VqYK57Gd Content-Type: text/x-diff; name="v37-0009-Add-support-for-min-max-aggregates-for-IVM.patch" Content-Disposition: attachment; filename="v37-0009-Add-support-for-min-max-aggregates-for-IVM.patch" Content-Transfer-Encoding: 7bit ^ permalink raw reply [nested|flat] 78+ messages in thread
* [PATCH v38 10/11] Add regression tests for Incremental View Maintenance @ 2026-05-29 09:31 Yugo Nagata <[email protected]> 0 siblings, 0 replies; 78+ messages in thread From: Yugo Nagata @ 2026-05-29 09:31 UTC (permalink / raw) --- .../isolation/expected/ivm-create-insert.out | 285 +++++ .../isolation/expected/ivm-create-insert2.out | 305 +++++ .../isolation/expected/ivm-create-insert3.out | 305 +++++ .../isolation/expected/ivm-insert-insert.out | 497 ++++++++ .../isolation/expected/ivm-insert-insert2.out | 373 ++++++ .../isolation/expected/ivm-insert-insert3.out | 373 ++++++ .../isolation/expected/ivm-refresh-insert.out | 213 ++++ .../expected/ivm-refresh-insert2.out | 191 +++ .../expected/ivm-refresh-insert3.out | 191 +++ src/test/isolation/isolation_schedule | 9 + .../isolation/specs/ivm-create-insert.spec | 47 + .../isolation/specs/ivm-create-insert2.spec | 54 + .../isolation/specs/ivm-create-insert3.spec | 54 + .../isolation/specs/ivm-insert-insert.spec | 62 + .../isolation/specs/ivm-insert-insert2.spec | 62 + .../isolation/specs/ivm-insert-insert3.spec | 62 + .../isolation/specs/ivm-refresh-insert.spec | 46 + .../isolation/specs/ivm-refresh-insert2.spec | 46 + .../isolation/specs/ivm-refresh-insert3.spec | 46 + .../regress/expected/incremental_matview.out | 1100 +++++++++++++++++ src/test/regress/parallel_schedule | 1 + src/test/regress/sql/incremental_matview.sql | 580 +++++++++ 22 files changed, 4902 insertions(+) create mode 100644 src/test/isolation/expected/ivm-create-insert.out create mode 100644 src/test/isolation/expected/ivm-create-insert2.out create mode 100644 src/test/isolation/expected/ivm-create-insert3.out create mode 100644 src/test/isolation/expected/ivm-insert-insert.out create mode 100644 src/test/isolation/expected/ivm-insert-insert2.out create mode 100644 src/test/isolation/expected/ivm-insert-insert3.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert2.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert3.out create mode 100644 src/test/isolation/specs/ivm-create-insert.spec create mode 100644 src/test/isolation/specs/ivm-create-insert2.spec create mode 100644 src/test/isolation/specs/ivm-create-insert3.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert2.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert3.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert2.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert3.spec create mode 100644 src/test/regress/expected/incremental_matview.out create mode 100644 src/test/regress/sql/incremental_matview.sql diff --git a/src/test/isolation/expected/ivm-create-insert.out b/src/test/isolation/expected/ivm-create-insert.out new file mode 100644 index 00000000000..5da00043aba --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert.out @@ -0,0 +1,285 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-create-insert2.out b/src/test/isolation/expected/ivm-create-insert2.out new file mode 100644 index 00000000000..907d892c6d4 --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert2.out @@ -0,0 +1,305 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + diff --git a/src/test/isolation/expected/ivm-create-insert3.out b/src/test/isolation/expected/ivm-create-insert3.out new file mode 100644 index 00000000000..907d892c6d4 --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert3.out @@ -0,0 +1,305 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert.out b/src/test/isolation/expected/ivm-insert-insert.out new file mode 100644 index 00000000000..5ca4cfea677 --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert.out @@ -0,0 +1,497 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; <waiting ...> +step c1: COMMIT; +step update2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; <waiting ...> +step c1: COMMIT; +step update2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; <waiting ...> +step c2: COMMIT; +step update1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; <waiting ...> +step c2: COMMIT; +step update1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); <waiting ...> +step c1: COMMIT; +step insert2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); <waiting ...> +step c1: COMMIT; +step insert2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); <waiting ...> +step c2: COMMIT; +step insert1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); <waiting ...> +step c2: COMMIT; +step insert1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert2.out b/src/test/isolation/expected/ivm-insert-insert2.out new file mode 100644 index 00000000000..e1c66d4de5e --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert2.out @@ -0,0 +1,373 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert3.out b/src/test/isolation/expected/ivm-insert-insert3.out new file mode 100644 index 00000000000..e1c66d4de5e --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert3.out @@ -0,0 +1,373 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert.out b/src/test/isolation/expected/ivm-refresh-insert.out new file mode 100644 index 00000000000..a925938bf1c --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert.out @@ -0,0 +1,213 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert2.out b/src/test/isolation/expected/ivm-refresh-insert2.out new file mode 100644 index 00000000000..dc1b16ae34e --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert2.out @@ -0,0 +1,191 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert3.out b/src/test/isolation/expected/ivm-refresh-insert3.out new file mode 100644 index 00000000000..dc1b16ae34e --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert3.out @@ -0,0 +1,191 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/isolation_schedule b/src/test/isolation/isolation_schedule index b8ebe92553c..6b7e873b370 100644 --- a/src/test/isolation/isolation_schedule +++ b/src/test/isolation/isolation_schedule @@ -128,3 +128,12 @@ test: matview-write-skew test: lock-nowait test: for-portion-of test: ddl-dependency-locking +test: ivm-create-insert +test: ivm-create-insert2 +test: ivm-create-insert3 +test: ivm-insert-insert +test: ivm-insert-insert2 +test: ivm-insert-insert3 +test: ivm-refresh-insert +test: ivm-refresh-insert2 +test: ivm-refresh-insert3 diff --git a/src/test/isolation/specs/ivm-create-insert.spec b/src/test/isolation/specs/ivm-create-insert.spec new file mode 100644 index 00000000000..ccd6fd080a9 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert.spec @@ -0,0 +1,47 @@ +# Test interaction between concurrent transactions performing +# create and insert in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-create-insert2.spec b/src/test/isolation/specs/ivm-create-insert2.spec new file mode 100644 index 00000000000..02cec85ae07 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert2.spec @@ -0,0 +1,54 @@ +# Test interaction between concurrent transactions performing +# create and insert in REPEATABLE READ isolation level +# +# Note: +# In this isolation level, it is possible that create_immv could +# create an inconsistent view not including effects of a concurrent +# transaction. So, an warning message is raised to suggest using it +# in READ COMMITTED or executing refresh_immv to make sure to +# make the view contents consistent. + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-create-insert3.spec b/src/test/isolation/specs/ivm-create-insert3.spec new file mode 100644 index 00000000000..19ce03185a4 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert3.spec @@ -0,0 +1,54 @@ +# Test interaction between concurrent transactions performing +# create and insert in SERIALIZABLE isolation level +# +# Note: +# In this isolation level, it is possible that create_immv could +# create an inconsistent view not including effects of a concurrent +# transaction. So, an warning message is raised to suggest using it +# in READ COMMITTED or executing refresh_immv to make sure to +# make the view contents consistent. + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert.spec b/src/test/isolation/specs/ivm-insert-insert.spec new file mode 100644 index 00000000000..b8f794ca191 --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert2.spec b/src/test/isolation/specs/ivm-insert-insert2.spec new file mode 100644 index 00000000000..ed086d1ba1e --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert2.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in REPEATABLE READ isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert3.spec b/src/test/isolation/specs/ivm-insert-insert3.spec new file mode 100644 index 00000000000..b18bd121033 --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert3.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in SERIALIZABLE isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert.spec b/src/test/isolation/specs/ivm-refresh-insert.spec new file mode 100644 index 00000000000..d7181251962 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert2.spec b/src/test/isolation/specs/ivm-refresh-insert2.spec new file mode 100644 index 00000000000..f2d1d5013f2 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert2.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in REPEATABLE READ isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert3.spec b/src/test/isolation/specs/ivm-refresh-insert3.spec new file mode 100644 index 00000000000..0ec2b1d1de0 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert3.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in SERIALIZABLE isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/regress/expected/incremental_matview.out b/src/test/regress/expected/incremental_matview.out new file mode 100644 index 00000000000..f215aa88e48 --- /dev/null +++ b/src/test/regress/expected/incremental_matview.out @@ -0,0 +1,1100 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ERROR: materialized view "mv_ivm_1" has not been populated +HINT: Use the REFRESH MATERIALIZED VIEW command. +REFRESH MATERIALIZED VIEW mv_ivm_1; +NOTICE: could not create an index on materialized view "mv_ivm_1" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 17 +(1 row) + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 1 +(1 row) + +ROLLBACK; +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_rename_index" on materialized view "mv_ivm_rename" +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +ERROR: IVM column can not be renamed +DROP MATERIALIZED VIEW mv_ivm_rename; +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_unique_index" on materialized view "mv_ivm_unique" +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +ERROR: unique index creation on IVM columns is not supported +DROP MATERIALIZED VIEW mv_ivm_unique; +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +NOTICE: could not create an index on materialized view "mv_ivm_func" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +NOTICE: could not create an index on materialized view "mv_ivm_no_tbl" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_duplicate" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +NOTICE: created index "mv_ivm_distinct_index" on materialized view "mv_ivm_distinct" +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 20 + 30 + 40 + 50 +(6 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +ROLLBACK; +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 120 | 2 | 60.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+---------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 220 | 2 | 110.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 20 | 1 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 120 | 2 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; + sum | count +-----+------- +(0 rows) + +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; + i | sum | count +---+-----+------- +(0 rows) + +ROLLBACK; +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 150 | 5 | 30.0000000000000000 +(1 row) + +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 210 | 6 | 35.0000000000000000 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +NOTICE: created index "mv_ivm_avg_bug_index" on materialized view "mv_ivm_avg_bug" +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 3 | 3.3333333333333333 + 2 | 80 | 3 | 26.6666666666666667 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_min_max_index" on materialized view "mv_ivm_min_max" +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 10 + 2 | 20 | 20 + 3 | 30 | 30 + 4 | 40 | 40 + 5 | 50 | 50 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 12 + 2 | 20 | 22 + 3 | 30 | 32 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 11 | 12 + 2 | 20 | 22 + 3 | 30 | 31 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min_max" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 50 +(1 row) + +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 0 | 70 +(1 row) + +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 60 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + | +(1 row) + +ROLLBACK; +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min; + min +----- + 10 +(1 row) + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + min +----- + 20 +(1 row) + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; + min +----- + 30 +(1 row) + +ROLLBACK; +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | sum +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | b +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ERROR: too many column names were specified +ROLLBACK; +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +NOTICE: could not create an index on materialized view "mv_self" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +----+---- + 10 | 10 + 20 | 20 + 30 | 30 +(3 rows) + +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 30 | 30 + 40 | 40 + 200 | 200 +(3 rows) + +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 130 | 130 + 300 | 300 +(4 rows) + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 70 | 70 + 70 | 77 + 77 | 70 + 77 | 77 + 130 | 130 + 300 | 300 +(8 rows) + +ROLLBACK; +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY v1; + v1 | v2 +----+----- + 10 | 100 + 20 | 200 + 30 | 300 +(3 rows) + +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv ORDER BY v1; + v1 | v2 +------+----- + 10 | 100 + 11 | 100 + 1020 | 200 + 1020 | 222 +(4 rows) + +ROLLBACK; +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +NOTICE: created index "mv_ri_index" on materialized view "mv_ri" +SELECT * FROM mv_ri ORDER BY i1; + i1 | i2 +----+---- + 1 | 1 + 2 | 2 + 3 | 3 +(3 rows) + +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; + i1 | i2 +----+---- + 3 | 3 + 10 | 10 +(2 rows) + +ROLLBACK; +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | +(2 rows) + +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | 20 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i +--- +(0 rows) + +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; + i +--- + 1 + +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 30 + | 3 +(2 rows) + +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 300 + | 30 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 1 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 4 +(1 row) + +ROLLBACK; +-- IMMV containing user defined type +BEGIN; +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: return type mytype is only a shell +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: argument type mytype is only a shell +LINE 1: CREATE FUNCTION mytype_out(mytype) + ^ +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +NOTICE: could not create an index on materialized view "mv_mytype" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + x +--- + 1 +(1 row) + +ROLLBACK; +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +ERROR: OUTER JOIN is not supported on incrementally maintainable materialized view +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +ERROR: CTE is not supported on incrementally maintainable materialized view +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +ERROR: ORDER BY clause is not supported on incrementally maintainable materialized view +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; +ERROR: HAVING clause is not supported on incrementally maintainable materialized view +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; +ERROR: mutable function is not supported on incrementally maintainable materialized view +HINT: functions must be marked IMMUTABLE +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; +ERROR: LIMIT/OFFSET clause is not supported on incrementally maintainable materialized view +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; +ERROR: DISTINCT ON is not supported on incrementally maintainable materialized view +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); +ERROR: TABLESAMPLE clause is not supported on incrementally maintainable materialized view +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; +ERROR: window functions are not supported on incrementally maintainable materialized view +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +ERROR: aggregate function with FILTER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +ERROR: aggregate function with DISTINCT arguments is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +ERROR: aggregate function with ORDER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); +ERROR: GROUPING SETS, ROLLUP, or CUBE clauses is not supported on incrementally maintainable materialized view +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ERROR: inheritance parent is not supported on incrementally maintainable materialized view +ROLLBACK; +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; +ERROR: UNION/INTERSECT/EXCEPT statements are not supported on incrementally maintainable materialized view +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; +ERROR: empty target list is not supported on incrementally maintainable materialized view +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; +ERROR: FOR UPDATE/SHARE clause is not supported on incrementally maintainable materialized view +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; +ERROR: column name __ivm_count__ is not supported on incrementally maintainable materialized view +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; +ERROR: GROUP BY expression not appearing in select list is not supported on incrementally maintainable materialized view +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); +ERROR: VALUES is not supported on incrementally maintainable materialized view +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +NOTICE: role "regress_ivm_admin" does not exist, skipping +DROP USER IF EXISTS regress_ivm_user; +NOTICE: role "regress_ivm_user" does not exist, skipping +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +NOTICE: could not create an index on materialized view "ivm_rls" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user +(1 row) + +RESET SESSION AUTHORIZATION; +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user + 3 | baz | regress_ivm_user +(2 rows) + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +-- +(1 row) + +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+-------+------------------ + 2 | bar | regress_ivm_user + 3 | baz | regress_ivm_user + 6 | corge | regress_ivm_user +(3 rows) + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +NOTICE: could not create an index on materialized view "ivm_rls2" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +RESET SESSION AUTHORIZATION; +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +-- +(1 row) + +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + id | data | owner | num +----+-------+------------------+--------- + 2 | bar | regress_ivm_user | two + 3 | baz_2 | regress_ivm_user | three_2 + 6 | corge | regress_ivm_user | six +(3 rows) + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +NOTICE: could not create an index on materialized view "mv_update_same" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + i +--- + 2 +(1 row) + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +NOTICE: created index "mv_self_ref_index" on materialized view "mv_self_ref" +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; + a | b +----+---- + 11 | + 12 | 11 + 13 | 12 +(3 rows) + +ROLLBACK; +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; +NOTICE: created index "mv_idx1_index" on materialized view "mv_idx1" +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; +NOTICE: created index "mv_idx2_index" on materialized view "mv_idx2" +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; +NOTICE: created index "mv_idx3_index" on materialized view "mv_idx3" +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +NOTICE: could not create an index on materialized view "mv_idx4" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; +NOTICE: could not create an index on materialized view "mv_idx5" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); +NOTICE: could not create an index on materialized view "mv_idx6" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ERROR: data type json has no default operator class for access method "btree" +ROLLBACK; +-- cleanup +DROP TABLE rls_tbl CASCADE; +NOTICE: drop cascades to 2 other objects +DETAIL: drop cascades to materialized view ivm_rls +drop cascades to materialized view ivm_rls2 +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; +DROP TABLE mv_base_b CASCADE; +NOTICE: drop cascades to 3 other objects +DETAIL: drop cascades to materialized view mv_ivm_1 +drop cascades to view b_view +drop cascades to materialized view b_mview +DROP TABLE mv_base_a CASCADE; diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index 8fa0a6c47fb..7caca5f64fd 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -77,6 +77,7 @@ test: brin_bloom brin_multi # Another group of parallel tests # ---------- test: create_table_like alter_generic alter_operator misc async dbsize merge misc_functions nls sysviews tsrf tid tidscan tidrangescan collate.utf8 collate.icu.utf8 incremental_sort create_role without_overlaps generated_virtual +test: incremental_matview # collate.linux.utf8 and collate.icu.utf8 tests cannot be run in parallel with each other # psql depends on create_am diff --git a/src/test/regress/sql/incremental_matview.sql b/src/test/regress/sql/incremental_matview.sql new file mode 100644 index 00000000000..2d55c393d6f --- /dev/null +++ b/src/test/regress/sql/incremental_matview.sql @@ -0,0 +1,580 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); + +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +REFRESH MATERIALIZED VIEW mv_ivm_1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; + +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; +ROLLBACK; + +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +DROP MATERIALIZED VIEW mv_ivm_rename; + +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +DROP MATERIALIZED VIEW mv_ivm_unique; + +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; + + +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +ROLLBACK; + +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +ROLLBACK; + +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +ROLLBACK; + +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +ROLLBACK; + +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +ROLLBACK; + +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min; + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); + +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; +ROLLBACK; + +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +SELECT * FROM mv_self ORDER BY v1; +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; +SELECT * FROM mv_self ORDER BY v1; + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + +ROLLBACK; + +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +SELECT * FROM mv ORDER BY v1; +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; +SELECT * FROM mv ORDER BY v1; +ROLLBACK; + +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +SELECT * FROM mv_ri ORDER BY i1; +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; +ROLLBACK; + +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +-- IMMV containing user defined type +BEGIN; + +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); + +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; + +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); + +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); + +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + +ROLLBACK; + +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; + +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; + +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; + +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; + +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; + +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); + +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; + +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); + +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ROLLBACK; + +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; + +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; + +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; + +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; + +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; + +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; + +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); + +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +DROP USER IF EXISTS regress_ivm_user; +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; + +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); + +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; + +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; + +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; +RESET SESSION AUTHORIZATION; + +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +RESET SESSION AUTHORIZATION; + +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; +ROLLBACK; + +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); + +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; + +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; + +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; + +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; + +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); + +ROLLBACK; + +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ROLLBACK; + +-- cleanup + +DROP TABLE rls_tbl CASCADE; +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; + +DROP TABLE mv_base_b CASCADE; +DROP TABLE mv_base_a CASCADE; -- 2.43.0 --Multipart=_Wed__1_Jul_2026_00_04_01_+0900_OVSy2WWK_9aByzDJ Content-Type: text/x-diff; name="v38-0009-Add-support-for-min-max-aggregates-for-IVM.patch" Content-Disposition: attachment; filename="v38-0009-Add-support-for-min-max-aggregates-for-IVM.patch" Content-Transfer-Encoding: 7bit ^ permalink raw reply [nested|flat] 78+ messages in thread
* [PATCH v37 10/11] Add regression tests for Incremental View Maintenance @ 2026-05-29 09:31 Yugo Nagata <[email protected]> 0 siblings, 0 replies; 78+ messages in thread From: Yugo Nagata @ 2026-05-29 09:31 UTC (permalink / raw) --- src/test/isolation/isolation_schedule | 9 + .../regress/expected/incremental_matview.out | 1100 +++++++++++++++++ src/test/regress/parallel_schedule | 1 + src/test/regress/sql/incremental_matview.sql | 580 +++++++++ 4 files changed, 1690 insertions(+) create mode 100644 src/test/regress/expected/incremental_matview.out create mode 100644 src/test/regress/sql/incremental_matview.sql diff --git a/src/test/isolation/isolation_schedule b/src/test/isolation/isolation_schedule index 15c33fad4c5..111fd465207 100644 --- a/src/test/isolation/isolation_schedule +++ b/src/test/isolation/isolation_schedule @@ -127,3 +127,12 @@ test: matview-write-skew test: lock-nowait test: for-portion-of test: ddl-dependency-locking +test: ivm-create-insert +test: ivm-create-insert2 +test: ivm-create-insert3 +test: ivm-insert-insert +test: ivm-insert-insert2 +test: ivm-insert-insert3 +test: ivm-refresh-insert +test: ivm-refresh-insert2 +test: ivm-refresh-insert3 diff --git a/src/test/regress/expected/incremental_matview.out b/src/test/regress/expected/incremental_matview.out new file mode 100644 index 00000000000..f215aa88e48 --- /dev/null +++ b/src/test/regress/expected/incremental_matview.out @@ -0,0 +1,1100 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ERROR: materialized view "mv_ivm_1" has not been populated +HINT: Use the REFRESH MATERIALIZED VIEW command. +REFRESH MATERIALIZED VIEW mv_ivm_1; +NOTICE: could not create an index on materialized view "mv_ivm_1" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 17 +(1 row) + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 1 +(1 row) + +ROLLBACK; +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_rename_index" on materialized view "mv_ivm_rename" +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +ERROR: IVM column can not be renamed +DROP MATERIALIZED VIEW mv_ivm_rename; +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_unique_index" on materialized view "mv_ivm_unique" +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +ERROR: unique index creation on IVM columns is not supported +DROP MATERIALIZED VIEW mv_ivm_unique; +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +NOTICE: could not create an index on materialized view "mv_ivm_func" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +NOTICE: could not create an index on materialized view "mv_ivm_no_tbl" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_duplicate" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +NOTICE: created index "mv_ivm_distinct_index" on materialized view "mv_ivm_distinct" +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 20 + 30 + 40 + 50 +(6 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +ROLLBACK; +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 120 | 2 | 60.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+---------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 220 | 2 | 110.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 20 | 1 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 120 | 2 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; + sum | count +-----+------- +(0 rows) + +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; + i | sum | count +---+-----+------- +(0 rows) + +ROLLBACK; +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 150 | 5 | 30.0000000000000000 +(1 row) + +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 210 | 6 | 35.0000000000000000 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +NOTICE: created index "mv_ivm_avg_bug_index" on materialized view "mv_ivm_avg_bug" +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 3 | 3.3333333333333333 + 2 | 80 | 3 | 26.6666666666666667 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_min_max_index" on materialized view "mv_ivm_min_max" +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 10 + 2 | 20 | 20 + 3 | 30 | 30 + 4 | 40 | 40 + 5 | 50 | 50 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 12 + 2 | 20 | 22 + 3 | 30 | 32 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 11 | 12 + 2 | 20 | 22 + 3 | 30 | 31 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min_max" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 50 +(1 row) + +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 0 | 70 +(1 row) + +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 60 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + | +(1 row) + +ROLLBACK; +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min; + min +----- + 10 +(1 row) + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + min +----- + 20 +(1 row) + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; + min +----- + 30 +(1 row) + +ROLLBACK; +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | sum +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | b +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ERROR: too many column names were specified +ROLLBACK; +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +NOTICE: could not create an index on materialized view "mv_self" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +----+---- + 10 | 10 + 20 | 20 + 30 | 30 +(3 rows) + +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 30 | 30 + 40 | 40 + 200 | 200 +(3 rows) + +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 130 | 130 + 300 | 300 +(4 rows) + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 70 | 70 + 70 | 77 + 77 | 70 + 77 | 77 + 130 | 130 + 300 | 300 +(8 rows) + +ROLLBACK; +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY v1; + v1 | v2 +----+----- + 10 | 100 + 20 | 200 + 30 | 300 +(3 rows) + +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv ORDER BY v1; + v1 | v2 +------+----- + 10 | 100 + 11 | 100 + 1020 | 200 + 1020 | 222 +(4 rows) + +ROLLBACK; +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +NOTICE: created index "mv_ri_index" on materialized view "mv_ri" +SELECT * FROM mv_ri ORDER BY i1; + i1 | i2 +----+---- + 1 | 1 + 2 | 2 + 3 | 3 +(3 rows) + +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; + i1 | i2 +----+---- + 3 | 3 + 10 | 10 +(2 rows) + +ROLLBACK; +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | +(2 rows) + +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | 20 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i +--- +(0 rows) + +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; + i +--- + 1 + +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 30 + | 3 +(2 rows) + +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 300 + | 30 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 1 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 4 +(1 row) + +ROLLBACK; +-- IMMV containing user defined type +BEGIN; +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: return type mytype is only a shell +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: argument type mytype is only a shell +LINE 1: CREATE FUNCTION mytype_out(mytype) + ^ +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +NOTICE: could not create an index on materialized view "mv_mytype" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + x +--- + 1 +(1 row) + +ROLLBACK; +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +ERROR: OUTER JOIN is not supported on incrementally maintainable materialized view +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +ERROR: CTE is not supported on incrementally maintainable materialized view +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +ERROR: ORDER BY clause is not supported on incrementally maintainable materialized view +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; +ERROR: HAVING clause is not supported on incrementally maintainable materialized view +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; +ERROR: mutable function is not supported on incrementally maintainable materialized view +HINT: functions must be marked IMMUTABLE +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; +ERROR: LIMIT/OFFSET clause is not supported on incrementally maintainable materialized view +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; +ERROR: DISTINCT ON is not supported on incrementally maintainable materialized view +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); +ERROR: TABLESAMPLE clause is not supported on incrementally maintainable materialized view +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; +ERROR: window functions are not supported on incrementally maintainable materialized view +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +ERROR: aggregate function with FILTER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +ERROR: aggregate function with DISTINCT arguments is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +ERROR: aggregate function with ORDER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); +ERROR: GROUPING SETS, ROLLUP, or CUBE clauses is not supported on incrementally maintainable materialized view +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ERROR: inheritance parent is not supported on incrementally maintainable materialized view +ROLLBACK; +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; +ERROR: UNION/INTERSECT/EXCEPT statements are not supported on incrementally maintainable materialized view +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; +ERROR: empty target list is not supported on incrementally maintainable materialized view +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; +ERROR: FOR UPDATE/SHARE clause is not supported on incrementally maintainable materialized view +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; +ERROR: column name __ivm_count__ is not supported on incrementally maintainable materialized view +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; +ERROR: GROUP BY expression not appearing in select list is not supported on incrementally maintainable materialized view +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); +ERROR: VALUES is not supported on incrementally maintainable materialized view +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +NOTICE: role "regress_ivm_admin" does not exist, skipping +DROP USER IF EXISTS regress_ivm_user; +NOTICE: role "regress_ivm_user" does not exist, skipping +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +NOTICE: could not create an index on materialized view "ivm_rls" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user +(1 row) + +RESET SESSION AUTHORIZATION; +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user + 3 | baz | regress_ivm_user +(2 rows) + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +-- +(1 row) + +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+-------+------------------ + 2 | bar | regress_ivm_user + 3 | baz | regress_ivm_user + 6 | corge | regress_ivm_user +(3 rows) + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +NOTICE: could not create an index on materialized view "ivm_rls2" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +RESET SESSION AUTHORIZATION; +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +-- +(1 row) + +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + id | data | owner | num +----+-------+------------------+--------- + 2 | bar | regress_ivm_user | two + 3 | baz_2 | regress_ivm_user | three_2 + 6 | corge | regress_ivm_user | six +(3 rows) + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +NOTICE: could not create an index on materialized view "mv_update_same" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + i +--- + 2 +(1 row) + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +NOTICE: created index "mv_self_ref_index" on materialized view "mv_self_ref" +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; + a | b +----+---- + 11 | + 12 | 11 + 13 | 12 +(3 rows) + +ROLLBACK; +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; +NOTICE: created index "mv_idx1_index" on materialized view "mv_idx1" +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; +NOTICE: created index "mv_idx2_index" on materialized view "mv_idx2" +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; +NOTICE: created index "mv_idx3_index" on materialized view "mv_idx3" +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +NOTICE: could not create an index on materialized view "mv_idx4" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; +NOTICE: could not create an index on materialized view "mv_idx5" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); +NOTICE: could not create an index on materialized view "mv_idx6" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ERROR: data type json has no default operator class for access method "btree" +ROLLBACK; +-- cleanup +DROP TABLE rls_tbl CASCADE; +NOTICE: drop cascades to 2 other objects +DETAIL: drop cascades to materialized view ivm_rls +drop cascades to materialized view ivm_rls2 +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; +DROP TABLE mv_base_b CASCADE; +NOTICE: drop cascades to 3 other objects +DETAIL: drop cascades to materialized view mv_ivm_1 +drop cascades to view b_view +drop cascades to materialized view b_mview +DROP TABLE mv_base_a CASCADE; diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index 8fa0a6c47fb..7caca5f64fd 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -77,6 +77,7 @@ test: brin_bloom brin_multi # Another group of parallel tests # ---------- test: create_table_like alter_generic alter_operator misc async dbsize merge misc_functions nls sysviews tsrf tid tidscan tidrangescan collate.utf8 collate.icu.utf8 incremental_sort create_role without_overlaps generated_virtual +test: incremental_matview # collate.linux.utf8 and collate.icu.utf8 tests cannot be run in parallel with each other # psql depends on create_am diff --git a/src/test/regress/sql/incremental_matview.sql b/src/test/regress/sql/incremental_matview.sql new file mode 100644 index 00000000000..2d55c393d6f --- /dev/null +++ b/src/test/regress/sql/incremental_matview.sql @@ -0,0 +1,580 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); + +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +REFRESH MATERIALIZED VIEW mv_ivm_1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; + +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; +ROLLBACK; + +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +DROP MATERIALIZED VIEW mv_ivm_rename; + +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +DROP MATERIALIZED VIEW mv_ivm_unique; + +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; + + +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +ROLLBACK; + +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +ROLLBACK; + +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +ROLLBACK; + +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +ROLLBACK; + +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +ROLLBACK; + +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min; + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); + +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; +ROLLBACK; + +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +SELECT * FROM mv_self ORDER BY v1; +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; +SELECT * FROM mv_self ORDER BY v1; + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + +ROLLBACK; + +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +SELECT * FROM mv ORDER BY v1; +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; +SELECT * FROM mv ORDER BY v1; +ROLLBACK; + +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +SELECT * FROM mv_ri ORDER BY i1; +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; +ROLLBACK; + +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +-- IMMV containing user defined type +BEGIN; + +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); + +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; + +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); + +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); + +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + +ROLLBACK; + +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; + +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; + +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; + +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; + +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; + +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); + +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; + +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); + +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ROLLBACK; + +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; + +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; + +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; + +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; + +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; + +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; + +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); + +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +DROP USER IF EXISTS regress_ivm_user; +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; + +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); + +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; + +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; + +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; +RESET SESSION AUTHORIZATION; + +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +RESET SESSION AUTHORIZATION; + +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; +ROLLBACK; + +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); + +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; + +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; + +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; + +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; + +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); + +ROLLBACK; + +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ROLLBACK; + +-- cleanup + +DROP TABLE rls_tbl CASCADE; +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; + +DROP TABLE mv_base_b CASCADE; +DROP TABLE mv_base_a CASCADE; -- 2.43.0 --Multipart=_Fri__29_May_2026_23_14_17_+0900_Te0o73X2VqYK57Gd Content-Type: text/x-diff; name="v37-0009-Add-support-for-min-max-aggregates-for-IVM.patch" Content-Disposition: attachment; filename="v37-0009-Add-support-for-min-max-aggregates-for-IVM.patch" Content-Transfer-Encoding: 7bit ^ permalink raw reply [nested|flat] 78+ messages in thread
* [PATCH v39 7/8] Add regression tests for Incremental View Maintenance @ 2026-05-29 09:31 Yugo Nagata <[email protected]> 0 siblings, 0 replies; 78+ messages in thread From: Yugo Nagata @ 2026-05-29 09:31 UTC (permalink / raw) --- .../isolation/expected/ivm-create-insert.out | 285 ++++++++ .../isolation/expected/ivm-create-insert2.out | 305 ++++++++ .../isolation/expected/ivm-create-insert3.out | 305 ++++++++ .../isolation/expected/ivm-insert-insert.out | 497 +++++++++++++ .../isolation/expected/ivm-insert-insert2.out | 373 ++++++++++ .../isolation/expected/ivm-insert-insert3.out | 373 ++++++++++ .../isolation/expected/ivm-refresh-insert.out | 213 ++++++ .../expected/ivm-refresh-insert2.out | 191 +++++ .../expected/ivm-refresh-insert3.out | 191 +++++ src/test/isolation/isolation_schedule | 9 + .../isolation/specs/ivm-create-insert.spec | 47 ++ .../isolation/specs/ivm-create-insert2.spec | 54 ++ .../isolation/specs/ivm-create-insert3.spec | 54 ++ .../isolation/specs/ivm-insert-insert.spec | 62 ++ .../isolation/specs/ivm-insert-insert2.spec | 62 ++ .../isolation/specs/ivm-insert-insert3.spec | 62 ++ .../isolation/specs/ivm-refresh-insert.spec | 46 ++ .../isolation/specs/ivm-refresh-insert2.spec | 46 ++ .../isolation/specs/ivm-refresh-insert3.spec | 46 ++ .../regress/expected/incremental_matview.out | 667 ++++++++++++++++++ src/test/regress/parallel_schedule | 1 + src/test/regress/sql/incremental_matview.sql | 407 +++++++++++ 22 files changed, 4296 insertions(+) create mode 100644 src/test/isolation/expected/ivm-create-insert.out create mode 100644 src/test/isolation/expected/ivm-create-insert2.out create mode 100644 src/test/isolation/expected/ivm-create-insert3.out create mode 100644 src/test/isolation/expected/ivm-insert-insert.out create mode 100644 src/test/isolation/expected/ivm-insert-insert2.out create mode 100644 src/test/isolation/expected/ivm-insert-insert3.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert2.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert3.out create mode 100644 src/test/isolation/specs/ivm-create-insert.spec create mode 100644 src/test/isolation/specs/ivm-create-insert2.spec create mode 100644 src/test/isolation/specs/ivm-create-insert3.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert2.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert3.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert2.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert3.spec create mode 100644 src/test/regress/expected/incremental_matview.out create mode 100644 src/test/regress/sql/incremental_matview.sql diff --git a/src/test/isolation/expected/ivm-create-insert.out b/src/test/isolation/expected/ivm-create-insert.out new file mode 100644 index 00000000000..5da00043aba --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert.out @@ -0,0 +1,285 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-create-insert2.out b/src/test/isolation/expected/ivm-create-insert2.out new file mode 100644 index 00000000000..907d892c6d4 --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert2.out @@ -0,0 +1,305 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + diff --git a/src/test/isolation/expected/ivm-create-insert3.out b/src/test/isolation/expected/ivm-create-insert3.out new file mode 100644 index 00000000000..907d892c6d4 --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert3.out @@ -0,0 +1,305 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert.out b/src/test/isolation/expected/ivm-insert-insert.out new file mode 100644 index 00000000000..5ca4cfea677 --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert.out @@ -0,0 +1,497 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; <waiting ...> +step c1: COMMIT; +step update2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; <waiting ...> +step c1: COMMIT; +step update2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; <waiting ...> +step c2: COMMIT; +step update1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; <waiting ...> +step c2: COMMIT; +step update1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); <waiting ...> +step c1: COMMIT; +step insert2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); <waiting ...> +step c1: COMMIT; +step insert2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); <waiting ...> +step c2: COMMIT; +step insert1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); <waiting ...> +step c2: COMMIT; +step insert1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert2.out b/src/test/isolation/expected/ivm-insert-insert2.out new file mode 100644 index 00000000000..e1c66d4de5e --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert2.out @@ -0,0 +1,373 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert3.out b/src/test/isolation/expected/ivm-insert-insert3.out new file mode 100644 index 00000000000..e1c66d4de5e --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert3.out @@ -0,0 +1,373 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert.out b/src/test/isolation/expected/ivm-refresh-insert.out new file mode 100644 index 00000000000..a925938bf1c --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert.out @@ -0,0 +1,213 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert2.out b/src/test/isolation/expected/ivm-refresh-insert2.out new file mode 100644 index 00000000000..dc1b16ae34e --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert2.out @@ -0,0 +1,191 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert3.out b/src/test/isolation/expected/ivm-refresh-insert3.out new file mode 100644 index 00000000000..dc1b16ae34e --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert3.out @@ -0,0 +1,191 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/isolation_schedule b/src/test/isolation/isolation_schedule index b8ebe92553c..6b7e873b370 100644 --- a/src/test/isolation/isolation_schedule +++ b/src/test/isolation/isolation_schedule @@ -128,3 +128,12 @@ test: matview-write-skew test: lock-nowait test: for-portion-of test: ddl-dependency-locking +test: ivm-create-insert +test: ivm-create-insert2 +test: ivm-create-insert3 +test: ivm-insert-insert +test: ivm-insert-insert2 +test: ivm-insert-insert3 +test: ivm-refresh-insert +test: ivm-refresh-insert2 +test: ivm-refresh-insert3 diff --git a/src/test/isolation/specs/ivm-create-insert.spec b/src/test/isolation/specs/ivm-create-insert.spec new file mode 100644 index 00000000000..ccd6fd080a9 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert.spec @@ -0,0 +1,47 @@ +# Test interaction between concurrent transactions performing +# create and insert in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-create-insert2.spec b/src/test/isolation/specs/ivm-create-insert2.spec new file mode 100644 index 00000000000..02cec85ae07 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert2.spec @@ -0,0 +1,54 @@ +# Test interaction between concurrent transactions performing +# create and insert in REPEATABLE READ isolation level +# +# Note: +# In this isolation level, it is possible that create_immv could +# create an inconsistent view not including effects of a concurrent +# transaction. So, an warning message is raised to suggest using it +# in READ COMMITTED or executing refresh_immv to make sure to +# make the view contents consistent. + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-create-insert3.spec b/src/test/isolation/specs/ivm-create-insert3.spec new file mode 100644 index 00000000000..19ce03185a4 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert3.spec @@ -0,0 +1,54 @@ +# Test interaction between concurrent transactions performing +# create and insert in SERIALIZABLE isolation level +# +# Note: +# In this isolation level, it is possible that create_immv could +# create an inconsistent view not including effects of a concurrent +# transaction. So, an warning message is raised to suggest using it +# in READ COMMITTED or executing refresh_immv to make sure to +# make the view contents consistent. + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert.spec b/src/test/isolation/specs/ivm-insert-insert.spec new file mode 100644 index 00000000000..b8f794ca191 --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert2.spec b/src/test/isolation/specs/ivm-insert-insert2.spec new file mode 100644 index 00000000000..ed086d1ba1e --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert2.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in REPEATABLE READ isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert3.spec b/src/test/isolation/specs/ivm-insert-insert3.spec new file mode 100644 index 00000000000..b18bd121033 --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert3.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in SERIALIZABLE isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert.spec b/src/test/isolation/specs/ivm-refresh-insert.spec new file mode 100644 index 00000000000..d7181251962 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert2.spec b/src/test/isolation/specs/ivm-refresh-insert2.spec new file mode 100644 index 00000000000..f2d1d5013f2 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert2.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in REPEATABLE READ isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert3.spec b/src/test/isolation/specs/ivm-refresh-insert3.spec new file mode 100644 index 00000000000..0ec2b1d1de0 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert3.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in SERIALIZABLE isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/regress/expected/incremental_matview.out b/src/test/regress/expected/incremental_matview.out new file mode 100644 index 00000000000..c7fd19fdca3 --- /dev/null +++ b/src/test/regress/expected/incremental_matview.out @@ -0,0 +1,667 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ERROR: materialized view "mv_ivm_1" has not been populated +HINT: Use the REFRESH MATERIALIZED VIEW command. +REFRESH MATERIALIZED VIEW mv_ivm_1; +NOTICE: could not create an index on materialized view "mv_ivm_1" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 17 +(1 row) + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 1 +(1 row) + +ROLLBACK; +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- DISTINCT not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT * FROM mv_base_a; +ERROR: DISTINCT is not supported on incrementally maintainable materialized view +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +NOTICE: could not create an index on materialized view "mv_ivm_func" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +NOTICE: could not create an index on materialized view "mv_ivm_no_tbl" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- result of materialized view have duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_duplicate" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 20 + 30 + 40 + 50 +(6 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +ROLLBACK; +-- aggregate not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +ERROR: aggregate function is not supported on incrementally maintainable materialized view +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +NOTICE: could not create an index on materialized view "mv_self" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +----+---- + 10 | 10 + 20 | 20 + 30 | 30 +(3 rows) + +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 30 | 30 + 40 | 40 + 200 | 200 +(3 rows) + +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 130 | 130 + 300 | 300 +(4 rows) + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 70 | 70 + 70 | 77 + 77 | 70 + 77 | 77 + 130 | 130 + 300 | 300 +(8 rows) + +ROLLBACK; +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY v1; + v1 | v2 +----+----- + 10 | 100 + 20 | 200 + 30 | 300 +(3 rows) + +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv ORDER BY v1; + v1 | v2 +------+----- + 10 | 100 + 11 | 100 + 1020 | 200 + 1020 | 222 +(4 rows) + +ROLLBACK; +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +NOTICE: created index "mv_ri_index" on materialized view "mv_ri" +SELECT * FROM mv_ri ORDER BY i1; + i1 | i2 +----+---- + 1 | 1 + 2 | 2 + 3 | 3 +(3 rows) + +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; + i1 | i2 +----+---- + 3 | 3 + 10 | 10 +(2 rows) + +ROLLBACK; +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | +(2 rows) + +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | 20 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i +--- +(0 rows) + +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; + i +--- + 1 + +(2 rows) + +ROLLBACK; +-- IMMV containing user defined type +BEGIN; +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: return type mytype is only a shell +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: argument type mytype is only a shell +LINE 1: CREATE FUNCTION mytype_out(mytype) + ^ +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +NOTICE: could not create an index on materialized view "mv_mytype" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + x +--- + 1 +(1 row) + +ROLLBACK; +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +ERROR: OUTER JOIN is not supported on incrementally maintainable materialized view +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +ERROR: CTE is not supported on incrementally maintainable materialized view +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +ERROR: ORDER BY clause is not supported on incrementally maintainable materialized view +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; +ERROR: HAVING clause is not supported on incrementally maintainable materialized view +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; +ERROR: mutable function is not supported on incrementally maintainable materialized view +HINT: functions must be marked IMMUTABLE +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; +ERROR: LIMIT/OFFSET clause is not supported on incrementally maintainable materialized view +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; +ERROR: DISTINCT is not supported on incrementally maintainable materialized view +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); +ERROR: TABLESAMPLE clause is not supported on incrementally maintainable materialized view +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; +ERROR: window functions are not supported on incrementally maintainable materialized view +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ERROR: inheritance parent is not supported on incrementally maintainable materialized view +ROLLBACK; +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; +ERROR: UNION/INTERSECT/EXCEPT statements are not supported on incrementally maintainable materialized view +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; +ERROR: empty target list is not supported on incrementally maintainable materialized view +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; +ERROR: FOR UPDATE/SHARE clause is not supported on incrementally maintainable materialized view +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; +ERROR: column name __ivm_count__ is not supported on incrementally maintainable materialized view +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; +ERROR: aggregate function is not supported on incrementally maintainable materialized view +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); +ERROR: VALUES is not supported on incrementally maintainable materialized view +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +NOTICE: role "regress_ivm_admin" does not exist, skipping +DROP USER IF EXISTS regress_ivm_user; +NOTICE: role "regress_ivm_user" does not exist, skipping +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +NOTICE: could not create an index on materialized view "ivm_rls" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user +(1 row) + +RESET SESSION AUTHORIZATION; +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user + 3 | baz | regress_ivm_user +(2 rows) + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +-- +(1 row) + +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+-------+------------------ + 2 | bar | regress_ivm_user + 3 | baz | regress_ivm_user + 6 | corge | regress_ivm_user +(3 rows) + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +NOTICE: could not create an index on materialized view "ivm_rls2" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +RESET SESSION AUTHORIZATION; +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +-- +(1 row) + +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + id | data | owner | num +----+-------+------------------+--------- + 2 | bar | regress_ivm_user | two + 3 | baz_2 | regress_ivm_user | three_2 + 6 | corge | regress_ivm_user | six +(3 rows) + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +NOTICE: could not create an index on materialized view "mv_update_same" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + i +--- + 2 +(1 row) + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +NOTICE: created index "mv_self_ref_index" on materialized view "mv_self_ref" +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; + a | b +----+---- + 11 | + 12 | 11 + 13 | 12 +(3 rows) + +ROLLBACK; +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; +NOTICE: created index "mv_idx3_index" on materialized view "mv_idx3" +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +NOTICE: could not create an index on materialized view "mv_idx4" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; +NOTICE: could not create an index on materialized view "mv_idx5" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); +NOTICE: could not create an index on materialized view "mv_idx6" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ERROR: data type json has no default operator class for access method "btree" +ROLLBACK; +-- cleanup +DROP TABLE rls_tbl CASCADE; +NOTICE: drop cascades to 2 other objects +DETAIL: drop cascades to materialized view ivm_rls +drop cascades to materialized view ivm_rls2 +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; +DROP TABLE mv_base_b CASCADE; +NOTICE: drop cascades to 3 other objects +DETAIL: drop cascades to materialized view mv_ivm_1 +drop cascades to view b_view +drop cascades to materialized view b_mview +DROP TABLE mv_base_a CASCADE; diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index 8fa0a6c47fb..7caca5f64fd 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -77,6 +77,7 @@ test: brin_bloom brin_multi # Another group of parallel tests # ---------- test: create_table_like alter_generic alter_operator misc async dbsize merge misc_functions nls sysviews tsrf tid tidscan tidrangescan collate.utf8 collate.icu.utf8 incremental_sort create_role without_overlaps generated_virtual +test: incremental_matview # collate.linux.utf8 and collate.icu.utf8 tests cannot be run in parallel with each other # psql depends on create_am diff --git a/src/test/regress/sql/incremental_matview.sql b/src/test/regress/sql/incremental_matview.sql new file mode 100644 index 00000000000..7313ad82f3e --- /dev/null +++ b/src/test/regress/sql/incremental_matview.sql @@ -0,0 +1,407 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); + +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +REFRESH MATERIALIZED VIEW mv_ivm_1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; + +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; +ROLLBACK; + +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- DISTINCT not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT * FROM mv_base_a; + +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; + + +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +ROLLBACK; + +-- result of materialized view have duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +ROLLBACK; + +-- aggregate not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; + +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +SELECT * FROM mv_self ORDER BY v1; +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; +SELECT * FROM mv_self ORDER BY v1; + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + +ROLLBACK; + +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +SELECT * FROM mv ORDER BY v1; +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; +SELECT * FROM mv ORDER BY v1; +ROLLBACK; + +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +SELECT * FROM mv_ri ORDER BY i1; +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; +ROLLBACK; + +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +-- IMMV containing user defined type +BEGIN; + +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); + +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; + +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); + +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); + +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + +ROLLBACK; + +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; + +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; + +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; + +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; + +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; + +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); + +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; + +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ROLLBACK; + +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; + +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; + +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; + +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; + +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; + +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); + +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +DROP USER IF EXISTS regress_ivm_user; +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; + +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); + +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; + +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; + +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; +RESET SESSION AUTHORIZATION; + +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +RESET SESSION AUTHORIZATION; + +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; +ROLLBACK; + +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); + +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; + +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; + +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); + +ROLLBACK; + +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ROLLBACK; + +-- cleanup + +DROP TABLE rls_tbl CASCADE; +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; + +DROP TABLE mv_base_b CASCADE; +DROP TABLE mv_base_a CASCADE; -- 2.43.0 --Multipart=_Fri__3_Jul_2026_19_11_16_+0900_CskxSIu_iGcDMEyM Content-Type: text/x-diff; name="v39-0006-Add-Incremental-View-Maintenance-support.patch" Content-Disposition: attachment; filename="v39-0006-Add-Incremental-View-Maintenance-support.patch" Content-Transfer-Encoding: 7bit ^ permalink raw reply [nested|flat] 78+ messages in thread
* [PATCH v38 10/11] Add regression tests for Incremental View Maintenance @ 2026-05-29 09:31 Yugo Nagata <[email protected]> 0 siblings, 0 replies; 78+ messages in thread From: Yugo Nagata @ 2026-05-29 09:31 UTC (permalink / raw) --- .../isolation/expected/ivm-create-insert.out | 285 +++++ .../isolation/expected/ivm-create-insert2.out | 305 +++++ .../isolation/expected/ivm-create-insert3.out | 305 +++++ .../isolation/expected/ivm-insert-insert.out | 497 ++++++++ .../isolation/expected/ivm-insert-insert2.out | 373 ++++++ .../isolation/expected/ivm-insert-insert3.out | 373 ++++++ .../isolation/expected/ivm-refresh-insert.out | 213 ++++ .../expected/ivm-refresh-insert2.out | 191 +++ .../expected/ivm-refresh-insert3.out | 191 +++ src/test/isolation/isolation_schedule | 9 + .../isolation/specs/ivm-create-insert.spec | 47 + .../isolation/specs/ivm-create-insert2.spec | 54 + .../isolation/specs/ivm-create-insert3.spec | 54 + .../isolation/specs/ivm-insert-insert.spec | 62 + .../isolation/specs/ivm-insert-insert2.spec | 62 + .../isolation/specs/ivm-insert-insert3.spec | 62 + .../isolation/specs/ivm-refresh-insert.spec | 46 + .../isolation/specs/ivm-refresh-insert2.spec | 46 + .../isolation/specs/ivm-refresh-insert3.spec | 46 + .../regress/expected/incremental_matview.out | 1100 +++++++++++++++++ src/test/regress/parallel_schedule | 1 + src/test/regress/sql/incremental_matview.sql | 580 +++++++++ 22 files changed, 4902 insertions(+) create mode 100644 src/test/isolation/expected/ivm-create-insert.out create mode 100644 src/test/isolation/expected/ivm-create-insert2.out create mode 100644 src/test/isolation/expected/ivm-create-insert3.out create mode 100644 src/test/isolation/expected/ivm-insert-insert.out create mode 100644 src/test/isolation/expected/ivm-insert-insert2.out create mode 100644 src/test/isolation/expected/ivm-insert-insert3.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert2.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert3.out create mode 100644 src/test/isolation/specs/ivm-create-insert.spec create mode 100644 src/test/isolation/specs/ivm-create-insert2.spec create mode 100644 src/test/isolation/specs/ivm-create-insert3.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert2.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert3.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert2.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert3.spec create mode 100644 src/test/regress/expected/incremental_matview.out create mode 100644 src/test/regress/sql/incremental_matview.sql diff --git a/src/test/isolation/expected/ivm-create-insert.out b/src/test/isolation/expected/ivm-create-insert.out new file mode 100644 index 00000000000..5da00043aba --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert.out @@ -0,0 +1,285 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-create-insert2.out b/src/test/isolation/expected/ivm-create-insert2.out new file mode 100644 index 00000000000..907d892c6d4 --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert2.out @@ -0,0 +1,305 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + diff --git a/src/test/isolation/expected/ivm-create-insert3.out b/src/test/isolation/expected/ivm-create-insert3.out new file mode 100644 index 00000000000..907d892c6d4 --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert3.out @@ -0,0 +1,305 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert.out b/src/test/isolation/expected/ivm-insert-insert.out new file mode 100644 index 00000000000..5ca4cfea677 --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert.out @@ -0,0 +1,497 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; <waiting ...> +step c1: COMMIT; +step update2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; <waiting ...> +step c1: COMMIT; +step update2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; <waiting ...> +step c2: COMMIT; +step update1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; <waiting ...> +step c2: COMMIT; +step update1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); <waiting ...> +step c1: COMMIT; +step insert2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); <waiting ...> +step c1: COMMIT; +step insert2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); <waiting ...> +step c2: COMMIT; +step insert1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); <waiting ...> +step c2: COMMIT; +step insert1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert2.out b/src/test/isolation/expected/ivm-insert-insert2.out new file mode 100644 index 00000000000..e1c66d4de5e --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert2.out @@ -0,0 +1,373 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert3.out b/src/test/isolation/expected/ivm-insert-insert3.out new file mode 100644 index 00000000000..e1c66d4de5e --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert3.out @@ -0,0 +1,373 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert.out b/src/test/isolation/expected/ivm-refresh-insert.out new file mode 100644 index 00000000000..a925938bf1c --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert.out @@ -0,0 +1,213 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert2.out b/src/test/isolation/expected/ivm-refresh-insert2.out new file mode 100644 index 00000000000..dc1b16ae34e --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert2.out @@ -0,0 +1,191 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert3.out b/src/test/isolation/expected/ivm-refresh-insert3.out new file mode 100644 index 00000000000..dc1b16ae34e --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert3.out @@ -0,0 +1,191 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/isolation_schedule b/src/test/isolation/isolation_schedule index b8ebe92553c..6b7e873b370 100644 --- a/src/test/isolation/isolation_schedule +++ b/src/test/isolation/isolation_schedule @@ -128,3 +128,12 @@ test: matview-write-skew test: lock-nowait test: for-portion-of test: ddl-dependency-locking +test: ivm-create-insert +test: ivm-create-insert2 +test: ivm-create-insert3 +test: ivm-insert-insert +test: ivm-insert-insert2 +test: ivm-insert-insert3 +test: ivm-refresh-insert +test: ivm-refresh-insert2 +test: ivm-refresh-insert3 diff --git a/src/test/isolation/specs/ivm-create-insert.spec b/src/test/isolation/specs/ivm-create-insert.spec new file mode 100644 index 00000000000..ccd6fd080a9 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert.spec @@ -0,0 +1,47 @@ +# Test interaction between concurrent transactions performing +# create and insert in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-create-insert2.spec b/src/test/isolation/specs/ivm-create-insert2.spec new file mode 100644 index 00000000000..02cec85ae07 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert2.spec @@ -0,0 +1,54 @@ +# Test interaction between concurrent transactions performing +# create and insert in REPEATABLE READ isolation level +# +# Note: +# In this isolation level, it is possible that create_immv could +# create an inconsistent view not including effects of a concurrent +# transaction. So, an warning message is raised to suggest using it +# in READ COMMITTED or executing refresh_immv to make sure to +# make the view contents consistent. + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-create-insert3.spec b/src/test/isolation/specs/ivm-create-insert3.spec new file mode 100644 index 00000000000..19ce03185a4 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert3.spec @@ -0,0 +1,54 @@ +# Test interaction between concurrent transactions performing +# create and insert in SERIALIZABLE isolation level +# +# Note: +# In this isolation level, it is possible that create_immv could +# create an inconsistent view not including effects of a concurrent +# transaction. So, an warning message is raised to suggest using it +# in READ COMMITTED or executing refresh_immv to make sure to +# make the view contents consistent. + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert.spec b/src/test/isolation/specs/ivm-insert-insert.spec new file mode 100644 index 00000000000..b8f794ca191 --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert2.spec b/src/test/isolation/specs/ivm-insert-insert2.spec new file mode 100644 index 00000000000..ed086d1ba1e --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert2.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in REPEATABLE READ isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert3.spec b/src/test/isolation/specs/ivm-insert-insert3.spec new file mode 100644 index 00000000000..b18bd121033 --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert3.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in SERIALIZABLE isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert.spec b/src/test/isolation/specs/ivm-refresh-insert.spec new file mode 100644 index 00000000000..d7181251962 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert2.spec b/src/test/isolation/specs/ivm-refresh-insert2.spec new file mode 100644 index 00000000000..f2d1d5013f2 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert2.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in REPEATABLE READ isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert3.spec b/src/test/isolation/specs/ivm-refresh-insert3.spec new file mode 100644 index 00000000000..0ec2b1d1de0 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert3.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in SERIALIZABLE isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/regress/expected/incremental_matview.out b/src/test/regress/expected/incremental_matview.out new file mode 100644 index 00000000000..f215aa88e48 --- /dev/null +++ b/src/test/regress/expected/incremental_matview.out @@ -0,0 +1,1100 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ERROR: materialized view "mv_ivm_1" has not been populated +HINT: Use the REFRESH MATERIALIZED VIEW command. +REFRESH MATERIALIZED VIEW mv_ivm_1; +NOTICE: could not create an index on materialized view "mv_ivm_1" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 17 +(1 row) + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 1 +(1 row) + +ROLLBACK; +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_rename_index" on materialized view "mv_ivm_rename" +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +ERROR: IVM column can not be renamed +DROP MATERIALIZED VIEW mv_ivm_rename; +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_unique_index" on materialized view "mv_ivm_unique" +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +ERROR: unique index creation on IVM columns is not supported +DROP MATERIALIZED VIEW mv_ivm_unique; +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +NOTICE: could not create an index on materialized view "mv_ivm_func" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +NOTICE: could not create an index on materialized view "mv_ivm_no_tbl" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_duplicate" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +NOTICE: created index "mv_ivm_distinct_index" on materialized view "mv_ivm_distinct" +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 20 + 30 + 40 + 50 +(6 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +ROLLBACK; +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 120 | 2 | 60.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+---------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 220 | 2 | 110.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 20 | 1 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 120 | 2 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; + sum | count +-----+------- +(0 rows) + +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; + i | sum | count +---+-----+------- +(0 rows) + +ROLLBACK; +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 150 | 5 | 30.0000000000000000 +(1 row) + +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 210 | 6 | 35.0000000000000000 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +NOTICE: created index "mv_ivm_avg_bug_index" on materialized view "mv_ivm_avg_bug" +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 3 | 3.3333333333333333 + 2 | 80 | 3 | 26.6666666666666667 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_min_max_index" on materialized view "mv_ivm_min_max" +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 10 + 2 | 20 | 20 + 3 | 30 | 30 + 4 | 40 | 40 + 5 | 50 | 50 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 12 + 2 | 20 | 22 + 3 | 30 | 32 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 11 | 12 + 2 | 20 | 22 + 3 | 30 | 31 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min_max" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 50 +(1 row) + +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 0 | 70 +(1 row) + +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 60 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + | +(1 row) + +ROLLBACK; +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min; + min +----- + 10 +(1 row) + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + min +----- + 20 +(1 row) + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; + min +----- + 30 +(1 row) + +ROLLBACK; +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | sum +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | b +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ERROR: too many column names were specified +ROLLBACK; +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +NOTICE: could not create an index on materialized view "mv_self" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +----+---- + 10 | 10 + 20 | 20 + 30 | 30 +(3 rows) + +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 30 | 30 + 40 | 40 + 200 | 200 +(3 rows) + +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 130 | 130 + 300 | 300 +(4 rows) + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 70 | 70 + 70 | 77 + 77 | 70 + 77 | 77 + 130 | 130 + 300 | 300 +(8 rows) + +ROLLBACK; +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY v1; + v1 | v2 +----+----- + 10 | 100 + 20 | 200 + 30 | 300 +(3 rows) + +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv ORDER BY v1; + v1 | v2 +------+----- + 10 | 100 + 11 | 100 + 1020 | 200 + 1020 | 222 +(4 rows) + +ROLLBACK; +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +NOTICE: created index "mv_ri_index" on materialized view "mv_ri" +SELECT * FROM mv_ri ORDER BY i1; + i1 | i2 +----+---- + 1 | 1 + 2 | 2 + 3 | 3 +(3 rows) + +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; + i1 | i2 +----+---- + 3 | 3 + 10 | 10 +(2 rows) + +ROLLBACK; +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | +(2 rows) + +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | 20 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i +--- +(0 rows) + +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; + i +--- + 1 + +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 30 + | 3 +(2 rows) + +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 300 + | 30 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 1 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 4 +(1 row) + +ROLLBACK; +-- IMMV containing user defined type +BEGIN; +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: return type mytype is only a shell +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: argument type mytype is only a shell +LINE 1: CREATE FUNCTION mytype_out(mytype) + ^ +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +NOTICE: could not create an index on materialized view "mv_mytype" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + x +--- + 1 +(1 row) + +ROLLBACK; +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +ERROR: OUTER JOIN is not supported on incrementally maintainable materialized view +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +ERROR: CTE is not supported on incrementally maintainable materialized view +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +ERROR: ORDER BY clause is not supported on incrementally maintainable materialized view +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; +ERROR: HAVING clause is not supported on incrementally maintainable materialized view +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; +ERROR: mutable function is not supported on incrementally maintainable materialized view +HINT: functions must be marked IMMUTABLE +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; +ERROR: LIMIT/OFFSET clause is not supported on incrementally maintainable materialized view +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; +ERROR: DISTINCT ON is not supported on incrementally maintainable materialized view +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); +ERROR: TABLESAMPLE clause is not supported on incrementally maintainable materialized view +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; +ERROR: window functions are not supported on incrementally maintainable materialized view +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +ERROR: aggregate function with FILTER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +ERROR: aggregate function with DISTINCT arguments is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +ERROR: aggregate function with ORDER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); +ERROR: GROUPING SETS, ROLLUP, or CUBE clauses is not supported on incrementally maintainable materialized view +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ERROR: inheritance parent is not supported on incrementally maintainable materialized view +ROLLBACK; +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; +ERROR: UNION/INTERSECT/EXCEPT statements are not supported on incrementally maintainable materialized view +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; +ERROR: empty target list is not supported on incrementally maintainable materialized view +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; +ERROR: FOR UPDATE/SHARE clause is not supported on incrementally maintainable materialized view +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; +ERROR: column name __ivm_count__ is not supported on incrementally maintainable materialized view +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; +ERROR: GROUP BY expression not appearing in select list is not supported on incrementally maintainable materialized view +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); +ERROR: VALUES is not supported on incrementally maintainable materialized view +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +NOTICE: role "regress_ivm_admin" does not exist, skipping +DROP USER IF EXISTS regress_ivm_user; +NOTICE: role "regress_ivm_user" does not exist, skipping +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +NOTICE: could not create an index on materialized view "ivm_rls" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user +(1 row) + +RESET SESSION AUTHORIZATION; +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user + 3 | baz | regress_ivm_user +(2 rows) + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +-- +(1 row) + +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+-------+------------------ + 2 | bar | regress_ivm_user + 3 | baz | regress_ivm_user + 6 | corge | regress_ivm_user +(3 rows) + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +NOTICE: could not create an index on materialized view "ivm_rls2" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +RESET SESSION AUTHORIZATION; +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +-- +(1 row) + +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + id | data | owner | num +----+-------+------------------+--------- + 2 | bar | regress_ivm_user | two + 3 | baz_2 | regress_ivm_user | three_2 + 6 | corge | regress_ivm_user | six +(3 rows) + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +NOTICE: could not create an index on materialized view "mv_update_same" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + i +--- + 2 +(1 row) + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +NOTICE: created index "mv_self_ref_index" on materialized view "mv_self_ref" +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; + a | b +----+---- + 11 | + 12 | 11 + 13 | 12 +(3 rows) + +ROLLBACK; +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; +NOTICE: created index "mv_idx1_index" on materialized view "mv_idx1" +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; +NOTICE: created index "mv_idx2_index" on materialized view "mv_idx2" +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; +NOTICE: created index "mv_idx3_index" on materialized view "mv_idx3" +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +NOTICE: could not create an index on materialized view "mv_idx4" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; +NOTICE: could not create an index on materialized view "mv_idx5" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); +NOTICE: could not create an index on materialized view "mv_idx6" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ERROR: data type json has no default operator class for access method "btree" +ROLLBACK; +-- cleanup +DROP TABLE rls_tbl CASCADE; +NOTICE: drop cascades to 2 other objects +DETAIL: drop cascades to materialized view ivm_rls +drop cascades to materialized view ivm_rls2 +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; +DROP TABLE mv_base_b CASCADE; +NOTICE: drop cascades to 3 other objects +DETAIL: drop cascades to materialized view mv_ivm_1 +drop cascades to view b_view +drop cascades to materialized view b_mview +DROP TABLE mv_base_a CASCADE; diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index 8fa0a6c47fb..7caca5f64fd 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -77,6 +77,7 @@ test: brin_bloom brin_multi # Another group of parallel tests # ---------- test: create_table_like alter_generic alter_operator misc async dbsize merge misc_functions nls sysviews tsrf tid tidscan tidrangescan collate.utf8 collate.icu.utf8 incremental_sort create_role without_overlaps generated_virtual +test: incremental_matview # collate.linux.utf8 and collate.icu.utf8 tests cannot be run in parallel with each other # psql depends on create_am diff --git a/src/test/regress/sql/incremental_matview.sql b/src/test/regress/sql/incremental_matview.sql new file mode 100644 index 00000000000..2d55c393d6f --- /dev/null +++ b/src/test/regress/sql/incremental_matview.sql @@ -0,0 +1,580 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); + +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +REFRESH MATERIALIZED VIEW mv_ivm_1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; + +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; +ROLLBACK; + +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +DROP MATERIALIZED VIEW mv_ivm_rename; + +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +DROP MATERIALIZED VIEW mv_ivm_unique; + +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; + + +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +ROLLBACK; + +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +ROLLBACK; + +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +ROLLBACK; + +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +ROLLBACK; + +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +ROLLBACK; + +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min; + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); + +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; +ROLLBACK; + +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +SELECT * FROM mv_self ORDER BY v1; +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; +SELECT * FROM mv_self ORDER BY v1; + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + +ROLLBACK; + +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +SELECT * FROM mv ORDER BY v1; +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; +SELECT * FROM mv ORDER BY v1; +ROLLBACK; + +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +SELECT * FROM mv_ri ORDER BY i1; +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; +ROLLBACK; + +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +-- IMMV containing user defined type +BEGIN; + +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); + +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; + +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); + +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); + +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + +ROLLBACK; + +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; + +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; + +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; + +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; + +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; + +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); + +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; + +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); + +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ROLLBACK; + +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; + +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; + +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; + +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; + +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; + +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; + +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); + +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +DROP USER IF EXISTS regress_ivm_user; +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; + +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); + +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; + +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; + +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; +RESET SESSION AUTHORIZATION; + +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +RESET SESSION AUTHORIZATION; + +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; +ROLLBACK; + +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); + +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; + +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; + +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; + +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; + +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); + +ROLLBACK; + +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ROLLBACK; + +-- cleanup + +DROP TABLE rls_tbl CASCADE; +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; + +DROP TABLE mv_base_b CASCADE; +DROP TABLE mv_base_a CASCADE; -- 2.43.0 --Multipart=_Wed__1_Jul_2026_00_04_01_+0900_OVSy2WWK_9aByzDJ Content-Type: text/x-diff; name="v38-0009-Add-support-for-min-max-aggregates-for-IVM.patch" Content-Disposition: attachment; filename="v38-0009-Add-support-for-min-max-aggregates-for-IVM.patch" Content-Transfer-Encoding: 7bit ^ permalink raw reply [nested|flat] 78+ messages in thread
* [PATCH v39 7/8] Add regression tests for Incremental View Maintenance @ 2026-05-29 09:31 Yugo Nagata <[email protected]> 0 siblings, 0 replies; 78+ messages in thread From: Yugo Nagata @ 2026-05-29 09:31 UTC (permalink / raw) --- .../isolation/expected/ivm-create-insert.out | 285 ++++++++ .../isolation/expected/ivm-create-insert2.out | 305 ++++++++ .../isolation/expected/ivm-create-insert3.out | 305 ++++++++ .../isolation/expected/ivm-insert-insert.out | 497 +++++++++++++ .../isolation/expected/ivm-insert-insert2.out | 373 ++++++++++ .../isolation/expected/ivm-insert-insert3.out | 373 ++++++++++ .../isolation/expected/ivm-refresh-insert.out | 213 ++++++ .../expected/ivm-refresh-insert2.out | 191 +++++ .../expected/ivm-refresh-insert3.out | 191 +++++ src/test/isolation/isolation_schedule | 9 + .../isolation/specs/ivm-create-insert.spec | 47 ++ .../isolation/specs/ivm-create-insert2.spec | 54 ++ .../isolation/specs/ivm-create-insert3.spec | 54 ++ .../isolation/specs/ivm-insert-insert.spec | 62 ++ .../isolation/specs/ivm-insert-insert2.spec | 62 ++ .../isolation/specs/ivm-insert-insert3.spec | 62 ++ .../isolation/specs/ivm-refresh-insert.spec | 46 ++ .../isolation/specs/ivm-refresh-insert2.spec | 46 ++ .../isolation/specs/ivm-refresh-insert3.spec | 46 ++ .../regress/expected/incremental_matview.out | 667 ++++++++++++++++++ src/test/regress/parallel_schedule | 1 + src/test/regress/sql/incremental_matview.sql | 407 +++++++++++ 22 files changed, 4296 insertions(+) create mode 100644 src/test/isolation/expected/ivm-create-insert.out create mode 100644 src/test/isolation/expected/ivm-create-insert2.out create mode 100644 src/test/isolation/expected/ivm-create-insert3.out create mode 100644 src/test/isolation/expected/ivm-insert-insert.out create mode 100644 src/test/isolation/expected/ivm-insert-insert2.out create mode 100644 src/test/isolation/expected/ivm-insert-insert3.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert2.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert3.out create mode 100644 src/test/isolation/specs/ivm-create-insert.spec create mode 100644 src/test/isolation/specs/ivm-create-insert2.spec create mode 100644 src/test/isolation/specs/ivm-create-insert3.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert2.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert3.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert2.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert3.spec create mode 100644 src/test/regress/expected/incremental_matview.out create mode 100644 src/test/regress/sql/incremental_matview.sql diff --git a/src/test/isolation/expected/ivm-create-insert.out b/src/test/isolation/expected/ivm-create-insert.out new file mode 100644 index 00000000000..5da00043aba --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert.out @@ -0,0 +1,285 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-create-insert2.out b/src/test/isolation/expected/ivm-create-insert2.out new file mode 100644 index 00000000000..907d892c6d4 --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert2.out @@ -0,0 +1,305 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + diff --git a/src/test/isolation/expected/ivm-create-insert3.out b/src/test/isolation/expected/ivm-create-insert3.out new file mode 100644 index 00000000000..907d892c6d4 --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert3.out @@ -0,0 +1,305 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert.out b/src/test/isolation/expected/ivm-insert-insert.out new file mode 100644 index 00000000000..5ca4cfea677 --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert.out @@ -0,0 +1,497 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; <waiting ...> +step c1: COMMIT; +step update2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; <waiting ...> +step c1: COMMIT; +step update2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; <waiting ...> +step c2: COMMIT; +step update1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; <waiting ...> +step c2: COMMIT; +step update1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); <waiting ...> +step c1: COMMIT; +step insert2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); <waiting ...> +step c1: COMMIT; +step insert2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); <waiting ...> +step c2: COMMIT; +step insert1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); <waiting ...> +step c2: COMMIT; +step insert1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert2.out b/src/test/isolation/expected/ivm-insert-insert2.out new file mode 100644 index 00000000000..e1c66d4de5e --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert2.out @@ -0,0 +1,373 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert3.out b/src/test/isolation/expected/ivm-insert-insert3.out new file mode 100644 index 00000000000..e1c66d4de5e --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert3.out @@ -0,0 +1,373 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert.out b/src/test/isolation/expected/ivm-refresh-insert.out new file mode 100644 index 00000000000..a925938bf1c --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert.out @@ -0,0 +1,213 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert2.out b/src/test/isolation/expected/ivm-refresh-insert2.out new file mode 100644 index 00000000000..dc1b16ae34e --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert2.out @@ -0,0 +1,191 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert3.out b/src/test/isolation/expected/ivm-refresh-insert3.out new file mode 100644 index 00000000000..dc1b16ae34e --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert3.out @@ -0,0 +1,191 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/isolation_schedule b/src/test/isolation/isolation_schedule index b8ebe92553c..6b7e873b370 100644 --- a/src/test/isolation/isolation_schedule +++ b/src/test/isolation/isolation_schedule @@ -128,3 +128,12 @@ test: matview-write-skew test: lock-nowait test: for-portion-of test: ddl-dependency-locking +test: ivm-create-insert +test: ivm-create-insert2 +test: ivm-create-insert3 +test: ivm-insert-insert +test: ivm-insert-insert2 +test: ivm-insert-insert3 +test: ivm-refresh-insert +test: ivm-refresh-insert2 +test: ivm-refresh-insert3 diff --git a/src/test/isolation/specs/ivm-create-insert.spec b/src/test/isolation/specs/ivm-create-insert.spec new file mode 100644 index 00000000000..ccd6fd080a9 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert.spec @@ -0,0 +1,47 @@ +# Test interaction between concurrent transactions performing +# create and insert in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-create-insert2.spec b/src/test/isolation/specs/ivm-create-insert2.spec new file mode 100644 index 00000000000..02cec85ae07 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert2.spec @@ -0,0 +1,54 @@ +# Test interaction between concurrent transactions performing +# create and insert in REPEATABLE READ isolation level +# +# Note: +# In this isolation level, it is possible that create_immv could +# create an inconsistent view not including effects of a concurrent +# transaction. So, an warning message is raised to suggest using it +# in READ COMMITTED or executing refresh_immv to make sure to +# make the view contents consistent. + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-create-insert3.spec b/src/test/isolation/specs/ivm-create-insert3.spec new file mode 100644 index 00000000000..19ce03185a4 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert3.spec @@ -0,0 +1,54 @@ +# Test interaction between concurrent transactions performing +# create and insert in SERIALIZABLE isolation level +# +# Note: +# In this isolation level, it is possible that create_immv could +# create an inconsistent view not including effects of a concurrent +# transaction. So, an warning message is raised to suggest using it +# in READ COMMITTED or executing refresh_immv to make sure to +# make the view contents consistent. + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert.spec b/src/test/isolation/specs/ivm-insert-insert.spec new file mode 100644 index 00000000000..b8f794ca191 --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert2.spec b/src/test/isolation/specs/ivm-insert-insert2.spec new file mode 100644 index 00000000000..ed086d1ba1e --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert2.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in REPEATABLE READ isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert3.spec b/src/test/isolation/specs/ivm-insert-insert3.spec new file mode 100644 index 00000000000..b18bd121033 --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert3.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in SERIALIZABLE isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert.spec b/src/test/isolation/specs/ivm-refresh-insert.spec new file mode 100644 index 00000000000..d7181251962 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert2.spec b/src/test/isolation/specs/ivm-refresh-insert2.spec new file mode 100644 index 00000000000..f2d1d5013f2 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert2.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in REPEATABLE READ isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert3.spec b/src/test/isolation/specs/ivm-refresh-insert3.spec new file mode 100644 index 00000000000..0ec2b1d1de0 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert3.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in SERIALIZABLE isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/regress/expected/incremental_matview.out b/src/test/regress/expected/incremental_matview.out new file mode 100644 index 00000000000..c7fd19fdca3 --- /dev/null +++ b/src/test/regress/expected/incremental_matview.out @@ -0,0 +1,667 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ERROR: materialized view "mv_ivm_1" has not been populated +HINT: Use the REFRESH MATERIALIZED VIEW command. +REFRESH MATERIALIZED VIEW mv_ivm_1; +NOTICE: could not create an index on materialized view "mv_ivm_1" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 17 +(1 row) + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 1 +(1 row) + +ROLLBACK; +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- DISTINCT not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT * FROM mv_base_a; +ERROR: DISTINCT is not supported on incrementally maintainable materialized view +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +NOTICE: could not create an index on materialized view "mv_ivm_func" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +NOTICE: could not create an index on materialized view "mv_ivm_no_tbl" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- result of materialized view have duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_duplicate" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 20 + 30 + 40 + 50 +(6 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +ROLLBACK; +-- aggregate not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +ERROR: aggregate function is not supported on incrementally maintainable materialized view +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +NOTICE: could not create an index on materialized view "mv_self" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +----+---- + 10 | 10 + 20 | 20 + 30 | 30 +(3 rows) + +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 30 | 30 + 40 | 40 + 200 | 200 +(3 rows) + +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 130 | 130 + 300 | 300 +(4 rows) + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 70 | 70 + 70 | 77 + 77 | 70 + 77 | 77 + 130 | 130 + 300 | 300 +(8 rows) + +ROLLBACK; +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY v1; + v1 | v2 +----+----- + 10 | 100 + 20 | 200 + 30 | 300 +(3 rows) + +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv ORDER BY v1; + v1 | v2 +------+----- + 10 | 100 + 11 | 100 + 1020 | 200 + 1020 | 222 +(4 rows) + +ROLLBACK; +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +NOTICE: created index "mv_ri_index" on materialized view "mv_ri" +SELECT * FROM mv_ri ORDER BY i1; + i1 | i2 +----+---- + 1 | 1 + 2 | 2 + 3 | 3 +(3 rows) + +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; + i1 | i2 +----+---- + 3 | 3 + 10 | 10 +(2 rows) + +ROLLBACK; +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | +(2 rows) + +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | 20 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i +--- +(0 rows) + +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; + i +--- + 1 + +(2 rows) + +ROLLBACK; +-- IMMV containing user defined type +BEGIN; +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: return type mytype is only a shell +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: argument type mytype is only a shell +LINE 1: CREATE FUNCTION mytype_out(mytype) + ^ +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +NOTICE: could not create an index on materialized view "mv_mytype" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + x +--- + 1 +(1 row) + +ROLLBACK; +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +ERROR: OUTER JOIN is not supported on incrementally maintainable materialized view +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +ERROR: CTE is not supported on incrementally maintainable materialized view +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +ERROR: ORDER BY clause is not supported on incrementally maintainable materialized view +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; +ERROR: HAVING clause is not supported on incrementally maintainable materialized view +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; +ERROR: mutable function is not supported on incrementally maintainable materialized view +HINT: functions must be marked IMMUTABLE +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; +ERROR: LIMIT/OFFSET clause is not supported on incrementally maintainable materialized view +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; +ERROR: DISTINCT is not supported on incrementally maintainable materialized view +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); +ERROR: TABLESAMPLE clause is not supported on incrementally maintainable materialized view +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; +ERROR: window functions are not supported on incrementally maintainable materialized view +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ERROR: inheritance parent is not supported on incrementally maintainable materialized view +ROLLBACK; +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; +ERROR: UNION/INTERSECT/EXCEPT statements are not supported on incrementally maintainable materialized view +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; +ERROR: empty target list is not supported on incrementally maintainable materialized view +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; +ERROR: FOR UPDATE/SHARE clause is not supported on incrementally maintainable materialized view +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; +ERROR: column name __ivm_count__ is not supported on incrementally maintainable materialized view +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; +ERROR: aggregate function is not supported on incrementally maintainable materialized view +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); +ERROR: VALUES is not supported on incrementally maintainable materialized view +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +NOTICE: role "regress_ivm_admin" does not exist, skipping +DROP USER IF EXISTS regress_ivm_user; +NOTICE: role "regress_ivm_user" does not exist, skipping +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +NOTICE: could not create an index on materialized view "ivm_rls" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user +(1 row) + +RESET SESSION AUTHORIZATION; +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user + 3 | baz | regress_ivm_user +(2 rows) + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +-- +(1 row) + +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+-------+------------------ + 2 | bar | regress_ivm_user + 3 | baz | regress_ivm_user + 6 | corge | regress_ivm_user +(3 rows) + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +NOTICE: could not create an index on materialized view "ivm_rls2" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +RESET SESSION AUTHORIZATION; +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +-- +(1 row) + +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + id | data | owner | num +----+-------+------------------+--------- + 2 | bar | regress_ivm_user | two + 3 | baz_2 | regress_ivm_user | three_2 + 6 | corge | regress_ivm_user | six +(3 rows) + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +NOTICE: could not create an index on materialized view "mv_update_same" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + i +--- + 2 +(1 row) + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +NOTICE: created index "mv_self_ref_index" on materialized view "mv_self_ref" +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; + a | b +----+---- + 11 | + 12 | 11 + 13 | 12 +(3 rows) + +ROLLBACK; +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; +NOTICE: created index "mv_idx3_index" on materialized view "mv_idx3" +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +NOTICE: could not create an index on materialized view "mv_idx4" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; +NOTICE: could not create an index on materialized view "mv_idx5" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); +NOTICE: could not create an index on materialized view "mv_idx6" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ERROR: data type json has no default operator class for access method "btree" +ROLLBACK; +-- cleanup +DROP TABLE rls_tbl CASCADE; +NOTICE: drop cascades to 2 other objects +DETAIL: drop cascades to materialized view ivm_rls +drop cascades to materialized view ivm_rls2 +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; +DROP TABLE mv_base_b CASCADE; +NOTICE: drop cascades to 3 other objects +DETAIL: drop cascades to materialized view mv_ivm_1 +drop cascades to view b_view +drop cascades to materialized view b_mview +DROP TABLE mv_base_a CASCADE; diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index 8fa0a6c47fb..7caca5f64fd 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -77,6 +77,7 @@ test: brin_bloom brin_multi # Another group of parallel tests # ---------- test: create_table_like alter_generic alter_operator misc async dbsize merge misc_functions nls sysviews tsrf tid tidscan tidrangescan collate.utf8 collate.icu.utf8 incremental_sort create_role without_overlaps generated_virtual +test: incremental_matview # collate.linux.utf8 and collate.icu.utf8 tests cannot be run in parallel with each other # psql depends on create_am diff --git a/src/test/regress/sql/incremental_matview.sql b/src/test/regress/sql/incremental_matview.sql new file mode 100644 index 00000000000..7313ad82f3e --- /dev/null +++ b/src/test/regress/sql/incremental_matview.sql @@ -0,0 +1,407 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); + +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +REFRESH MATERIALIZED VIEW mv_ivm_1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; + +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; +ROLLBACK; + +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- DISTINCT not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT * FROM mv_base_a; + +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; + + +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +ROLLBACK; + +-- result of materialized view have duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +ROLLBACK; + +-- aggregate not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; + +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +SELECT * FROM mv_self ORDER BY v1; +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; +SELECT * FROM mv_self ORDER BY v1; + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + +ROLLBACK; + +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +SELECT * FROM mv ORDER BY v1; +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; +SELECT * FROM mv ORDER BY v1; +ROLLBACK; + +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +SELECT * FROM mv_ri ORDER BY i1; +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; +ROLLBACK; + +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +-- IMMV containing user defined type +BEGIN; + +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); + +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; + +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); + +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); + +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + +ROLLBACK; + +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; + +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; + +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; + +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; + +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; + +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); + +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; + +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ROLLBACK; + +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; + +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; + +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; + +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; + +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; + +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); + +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +DROP USER IF EXISTS regress_ivm_user; +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; + +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); + +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; + +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; + +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; +RESET SESSION AUTHORIZATION; + +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +RESET SESSION AUTHORIZATION; + +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; +ROLLBACK; + +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); + +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; + +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; + +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); + +ROLLBACK; + +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ROLLBACK; + +-- cleanup + +DROP TABLE rls_tbl CASCADE; +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; + +DROP TABLE mv_base_b CASCADE; +DROP TABLE mv_base_a CASCADE; -- 2.43.0 --Multipart=_Fri__3_Jul_2026_19_11_16_+0900_CskxSIu_iGcDMEyM Content-Type: text/x-diff; name="v39-0006-Add-Incremental-View-Maintenance-support.patch" Content-Disposition: attachment; filename="v39-0006-Add-Incremental-View-Maintenance-support.patch" Content-Transfer-Encoding: 7bit ^ permalink raw reply [nested|flat] 78+ messages in thread
* [PATCH v38 10/11] Add regression tests for Incremental View Maintenance @ 2026-05-29 09:31 Yugo Nagata <[email protected]> 0 siblings, 0 replies; 78+ messages in thread From: Yugo Nagata @ 2026-05-29 09:31 UTC (permalink / raw) --- .../isolation/expected/ivm-create-insert.out | 285 +++++ .../isolation/expected/ivm-create-insert2.out | 305 +++++ .../isolation/expected/ivm-create-insert3.out | 305 +++++ .../isolation/expected/ivm-insert-insert.out | 497 ++++++++ .../isolation/expected/ivm-insert-insert2.out | 373 ++++++ .../isolation/expected/ivm-insert-insert3.out | 373 ++++++ .../isolation/expected/ivm-refresh-insert.out | 213 ++++ .../expected/ivm-refresh-insert2.out | 191 +++ .../expected/ivm-refresh-insert3.out | 191 +++ src/test/isolation/isolation_schedule | 9 + .../isolation/specs/ivm-create-insert.spec | 47 + .../isolation/specs/ivm-create-insert2.spec | 54 + .../isolation/specs/ivm-create-insert3.spec | 54 + .../isolation/specs/ivm-insert-insert.spec | 62 + .../isolation/specs/ivm-insert-insert2.spec | 62 + .../isolation/specs/ivm-insert-insert3.spec | 62 + .../isolation/specs/ivm-refresh-insert.spec | 46 + .../isolation/specs/ivm-refresh-insert2.spec | 46 + .../isolation/specs/ivm-refresh-insert3.spec | 46 + .../regress/expected/incremental_matview.out | 1100 +++++++++++++++++ src/test/regress/parallel_schedule | 1 + src/test/regress/sql/incremental_matview.sql | 580 +++++++++ 22 files changed, 4902 insertions(+) create mode 100644 src/test/isolation/expected/ivm-create-insert.out create mode 100644 src/test/isolation/expected/ivm-create-insert2.out create mode 100644 src/test/isolation/expected/ivm-create-insert3.out create mode 100644 src/test/isolation/expected/ivm-insert-insert.out create mode 100644 src/test/isolation/expected/ivm-insert-insert2.out create mode 100644 src/test/isolation/expected/ivm-insert-insert3.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert2.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert3.out create mode 100644 src/test/isolation/specs/ivm-create-insert.spec create mode 100644 src/test/isolation/specs/ivm-create-insert2.spec create mode 100644 src/test/isolation/specs/ivm-create-insert3.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert2.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert3.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert2.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert3.spec create mode 100644 src/test/regress/expected/incremental_matview.out create mode 100644 src/test/regress/sql/incremental_matview.sql diff --git a/src/test/isolation/expected/ivm-create-insert.out b/src/test/isolation/expected/ivm-create-insert.out new file mode 100644 index 00000000000..5da00043aba --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert.out @@ -0,0 +1,285 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-create-insert2.out b/src/test/isolation/expected/ivm-create-insert2.out new file mode 100644 index 00000000000..907d892c6d4 --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert2.out @@ -0,0 +1,305 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + diff --git a/src/test/isolation/expected/ivm-create-insert3.out b/src/test/isolation/expected/ivm-create-insert3.out new file mode 100644 index 00000000000..907d892c6d4 --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert3.out @@ -0,0 +1,305 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert.out b/src/test/isolation/expected/ivm-insert-insert.out new file mode 100644 index 00000000000..5ca4cfea677 --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert.out @@ -0,0 +1,497 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; <waiting ...> +step c1: COMMIT; +step update2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; <waiting ...> +step c1: COMMIT; +step update2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; <waiting ...> +step c2: COMMIT; +step update1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; <waiting ...> +step c2: COMMIT; +step update1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); <waiting ...> +step c1: COMMIT; +step insert2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); <waiting ...> +step c1: COMMIT; +step insert2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); <waiting ...> +step c2: COMMIT; +step insert1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); <waiting ...> +step c2: COMMIT; +step insert1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert2.out b/src/test/isolation/expected/ivm-insert-insert2.out new file mode 100644 index 00000000000..e1c66d4de5e --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert2.out @@ -0,0 +1,373 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert3.out b/src/test/isolation/expected/ivm-insert-insert3.out new file mode 100644 index 00000000000..e1c66d4de5e --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert3.out @@ -0,0 +1,373 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert.out b/src/test/isolation/expected/ivm-refresh-insert.out new file mode 100644 index 00000000000..a925938bf1c --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert.out @@ -0,0 +1,213 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert2.out b/src/test/isolation/expected/ivm-refresh-insert2.out new file mode 100644 index 00000000000..dc1b16ae34e --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert2.out @@ -0,0 +1,191 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert3.out b/src/test/isolation/expected/ivm-refresh-insert3.out new file mode 100644 index 00000000000..dc1b16ae34e --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert3.out @@ -0,0 +1,191 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/isolation_schedule b/src/test/isolation/isolation_schedule index b8ebe92553c..6b7e873b370 100644 --- a/src/test/isolation/isolation_schedule +++ b/src/test/isolation/isolation_schedule @@ -128,3 +128,12 @@ test: matview-write-skew test: lock-nowait test: for-portion-of test: ddl-dependency-locking +test: ivm-create-insert +test: ivm-create-insert2 +test: ivm-create-insert3 +test: ivm-insert-insert +test: ivm-insert-insert2 +test: ivm-insert-insert3 +test: ivm-refresh-insert +test: ivm-refresh-insert2 +test: ivm-refresh-insert3 diff --git a/src/test/isolation/specs/ivm-create-insert.spec b/src/test/isolation/specs/ivm-create-insert.spec new file mode 100644 index 00000000000..ccd6fd080a9 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert.spec @@ -0,0 +1,47 @@ +# Test interaction between concurrent transactions performing +# create and insert in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-create-insert2.spec b/src/test/isolation/specs/ivm-create-insert2.spec new file mode 100644 index 00000000000..02cec85ae07 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert2.spec @@ -0,0 +1,54 @@ +# Test interaction between concurrent transactions performing +# create and insert in REPEATABLE READ isolation level +# +# Note: +# In this isolation level, it is possible that create_immv could +# create an inconsistent view not including effects of a concurrent +# transaction. So, an warning message is raised to suggest using it +# in READ COMMITTED or executing refresh_immv to make sure to +# make the view contents consistent. + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-create-insert3.spec b/src/test/isolation/specs/ivm-create-insert3.spec new file mode 100644 index 00000000000..19ce03185a4 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert3.spec @@ -0,0 +1,54 @@ +# Test interaction between concurrent transactions performing +# create and insert in SERIALIZABLE isolation level +# +# Note: +# In this isolation level, it is possible that create_immv could +# create an inconsistent view not including effects of a concurrent +# transaction. So, an warning message is raised to suggest using it +# in READ COMMITTED or executing refresh_immv to make sure to +# make the view contents consistent. + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert.spec b/src/test/isolation/specs/ivm-insert-insert.spec new file mode 100644 index 00000000000..b8f794ca191 --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert2.spec b/src/test/isolation/specs/ivm-insert-insert2.spec new file mode 100644 index 00000000000..ed086d1ba1e --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert2.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in REPEATABLE READ isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert3.spec b/src/test/isolation/specs/ivm-insert-insert3.spec new file mode 100644 index 00000000000..b18bd121033 --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert3.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in SERIALIZABLE isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert.spec b/src/test/isolation/specs/ivm-refresh-insert.spec new file mode 100644 index 00000000000..d7181251962 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert2.spec b/src/test/isolation/specs/ivm-refresh-insert2.spec new file mode 100644 index 00000000000..f2d1d5013f2 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert2.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in REPEATABLE READ isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert3.spec b/src/test/isolation/specs/ivm-refresh-insert3.spec new file mode 100644 index 00000000000..0ec2b1d1de0 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert3.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in SERIALIZABLE isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/regress/expected/incremental_matview.out b/src/test/regress/expected/incremental_matview.out new file mode 100644 index 00000000000..f215aa88e48 --- /dev/null +++ b/src/test/regress/expected/incremental_matview.out @@ -0,0 +1,1100 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ERROR: materialized view "mv_ivm_1" has not been populated +HINT: Use the REFRESH MATERIALIZED VIEW command. +REFRESH MATERIALIZED VIEW mv_ivm_1; +NOTICE: could not create an index on materialized view "mv_ivm_1" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 17 +(1 row) + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 1 +(1 row) + +ROLLBACK; +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_rename_index" on materialized view "mv_ivm_rename" +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +ERROR: IVM column can not be renamed +DROP MATERIALIZED VIEW mv_ivm_rename; +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_unique_index" on materialized view "mv_ivm_unique" +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +ERROR: unique index creation on IVM columns is not supported +DROP MATERIALIZED VIEW mv_ivm_unique; +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +NOTICE: could not create an index on materialized view "mv_ivm_func" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +NOTICE: could not create an index on materialized view "mv_ivm_no_tbl" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_duplicate" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +NOTICE: created index "mv_ivm_distinct_index" on materialized view "mv_ivm_distinct" +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 20 + 30 + 40 + 50 +(6 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +ROLLBACK; +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 120 | 2 | 60.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+---------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 220 | 2 | 110.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 20 | 1 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 120 | 2 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; + sum | count +-----+------- +(0 rows) + +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; + i | sum | count +---+-----+------- +(0 rows) + +ROLLBACK; +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 150 | 5 | 30.0000000000000000 +(1 row) + +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 210 | 6 | 35.0000000000000000 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +NOTICE: created index "mv_ivm_avg_bug_index" on materialized view "mv_ivm_avg_bug" +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 3 | 3.3333333333333333 + 2 | 80 | 3 | 26.6666666666666667 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_min_max_index" on materialized view "mv_ivm_min_max" +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 10 + 2 | 20 | 20 + 3 | 30 | 30 + 4 | 40 | 40 + 5 | 50 | 50 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 12 + 2 | 20 | 22 + 3 | 30 | 32 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 11 | 12 + 2 | 20 | 22 + 3 | 30 | 31 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min_max" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 50 +(1 row) + +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 0 | 70 +(1 row) + +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 60 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + | +(1 row) + +ROLLBACK; +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min; + min +----- + 10 +(1 row) + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + min +----- + 20 +(1 row) + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; + min +----- + 30 +(1 row) + +ROLLBACK; +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | sum +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | b +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ERROR: too many column names were specified +ROLLBACK; +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +NOTICE: could not create an index on materialized view "mv_self" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +----+---- + 10 | 10 + 20 | 20 + 30 | 30 +(3 rows) + +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 30 | 30 + 40 | 40 + 200 | 200 +(3 rows) + +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 130 | 130 + 300 | 300 +(4 rows) + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 70 | 70 + 70 | 77 + 77 | 70 + 77 | 77 + 130 | 130 + 300 | 300 +(8 rows) + +ROLLBACK; +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY v1; + v1 | v2 +----+----- + 10 | 100 + 20 | 200 + 30 | 300 +(3 rows) + +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv ORDER BY v1; + v1 | v2 +------+----- + 10 | 100 + 11 | 100 + 1020 | 200 + 1020 | 222 +(4 rows) + +ROLLBACK; +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +NOTICE: created index "mv_ri_index" on materialized view "mv_ri" +SELECT * FROM mv_ri ORDER BY i1; + i1 | i2 +----+---- + 1 | 1 + 2 | 2 + 3 | 3 +(3 rows) + +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; + i1 | i2 +----+---- + 3 | 3 + 10 | 10 +(2 rows) + +ROLLBACK; +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | +(2 rows) + +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | 20 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i +--- +(0 rows) + +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; + i +--- + 1 + +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 30 + | 3 +(2 rows) + +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 300 + | 30 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 1 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 4 +(1 row) + +ROLLBACK; +-- IMMV containing user defined type +BEGIN; +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: return type mytype is only a shell +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: argument type mytype is only a shell +LINE 1: CREATE FUNCTION mytype_out(mytype) + ^ +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +NOTICE: could not create an index on materialized view "mv_mytype" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + x +--- + 1 +(1 row) + +ROLLBACK; +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +ERROR: OUTER JOIN is not supported on incrementally maintainable materialized view +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +ERROR: CTE is not supported on incrementally maintainable materialized view +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +ERROR: ORDER BY clause is not supported on incrementally maintainable materialized view +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; +ERROR: HAVING clause is not supported on incrementally maintainable materialized view +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; +ERROR: mutable function is not supported on incrementally maintainable materialized view +HINT: functions must be marked IMMUTABLE +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; +ERROR: LIMIT/OFFSET clause is not supported on incrementally maintainable materialized view +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; +ERROR: DISTINCT ON is not supported on incrementally maintainable materialized view +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); +ERROR: TABLESAMPLE clause is not supported on incrementally maintainable materialized view +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; +ERROR: window functions are not supported on incrementally maintainable materialized view +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +ERROR: aggregate function with FILTER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +ERROR: aggregate function with DISTINCT arguments is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +ERROR: aggregate function with ORDER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); +ERROR: GROUPING SETS, ROLLUP, or CUBE clauses is not supported on incrementally maintainable materialized view +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ERROR: inheritance parent is not supported on incrementally maintainable materialized view +ROLLBACK; +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; +ERROR: UNION/INTERSECT/EXCEPT statements are not supported on incrementally maintainable materialized view +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; +ERROR: empty target list is not supported on incrementally maintainable materialized view +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; +ERROR: FOR UPDATE/SHARE clause is not supported on incrementally maintainable materialized view +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; +ERROR: column name __ivm_count__ is not supported on incrementally maintainable materialized view +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; +ERROR: GROUP BY expression not appearing in select list is not supported on incrementally maintainable materialized view +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); +ERROR: VALUES is not supported on incrementally maintainable materialized view +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +NOTICE: role "regress_ivm_admin" does not exist, skipping +DROP USER IF EXISTS regress_ivm_user; +NOTICE: role "regress_ivm_user" does not exist, skipping +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +NOTICE: could not create an index on materialized view "ivm_rls" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user +(1 row) + +RESET SESSION AUTHORIZATION; +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user + 3 | baz | regress_ivm_user +(2 rows) + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +-- +(1 row) + +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+-------+------------------ + 2 | bar | regress_ivm_user + 3 | baz | regress_ivm_user + 6 | corge | regress_ivm_user +(3 rows) + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +NOTICE: could not create an index on materialized view "ivm_rls2" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +RESET SESSION AUTHORIZATION; +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +-- +(1 row) + +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + id | data | owner | num +----+-------+------------------+--------- + 2 | bar | regress_ivm_user | two + 3 | baz_2 | regress_ivm_user | three_2 + 6 | corge | regress_ivm_user | six +(3 rows) + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +NOTICE: could not create an index on materialized view "mv_update_same" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + i +--- + 2 +(1 row) + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +NOTICE: created index "mv_self_ref_index" on materialized view "mv_self_ref" +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; + a | b +----+---- + 11 | + 12 | 11 + 13 | 12 +(3 rows) + +ROLLBACK; +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; +NOTICE: created index "mv_idx1_index" on materialized view "mv_idx1" +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; +NOTICE: created index "mv_idx2_index" on materialized view "mv_idx2" +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; +NOTICE: created index "mv_idx3_index" on materialized view "mv_idx3" +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +NOTICE: could not create an index on materialized view "mv_idx4" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; +NOTICE: could not create an index on materialized view "mv_idx5" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); +NOTICE: could not create an index on materialized view "mv_idx6" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ERROR: data type json has no default operator class for access method "btree" +ROLLBACK; +-- cleanup +DROP TABLE rls_tbl CASCADE; +NOTICE: drop cascades to 2 other objects +DETAIL: drop cascades to materialized view ivm_rls +drop cascades to materialized view ivm_rls2 +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; +DROP TABLE mv_base_b CASCADE; +NOTICE: drop cascades to 3 other objects +DETAIL: drop cascades to materialized view mv_ivm_1 +drop cascades to view b_view +drop cascades to materialized view b_mview +DROP TABLE mv_base_a CASCADE; diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index 8fa0a6c47fb..7caca5f64fd 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -77,6 +77,7 @@ test: brin_bloom brin_multi # Another group of parallel tests # ---------- test: create_table_like alter_generic alter_operator misc async dbsize merge misc_functions nls sysviews tsrf tid tidscan tidrangescan collate.utf8 collate.icu.utf8 incremental_sort create_role without_overlaps generated_virtual +test: incremental_matview # collate.linux.utf8 and collate.icu.utf8 tests cannot be run in parallel with each other # psql depends on create_am diff --git a/src/test/regress/sql/incremental_matview.sql b/src/test/regress/sql/incremental_matview.sql new file mode 100644 index 00000000000..2d55c393d6f --- /dev/null +++ b/src/test/regress/sql/incremental_matview.sql @@ -0,0 +1,580 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); + +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +REFRESH MATERIALIZED VIEW mv_ivm_1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; + +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; +ROLLBACK; + +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +DROP MATERIALIZED VIEW mv_ivm_rename; + +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +DROP MATERIALIZED VIEW mv_ivm_unique; + +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; + + +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +ROLLBACK; + +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +ROLLBACK; + +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +ROLLBACK; + +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +ROLLBACK; + +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +ROLLBACK; + +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min; + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); + +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; +ROLLBACK; + +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +SELECT * FROM mv_self ORDER BY v1; +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; +SELECT * FROM mv_self ORDER BY v1; + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + +ROLLBACK; + +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +SELECT * FROM mv ORDER BY v1; +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; +SELECT * FROM mv ORDER BY v1; +ROLLBACK; + +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +SELECT * FROM mv_ri ORDER BY i1; +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; +ROLLBACK; + +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +-- IMMV containing user defined type +BEGIN; + +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); + +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; + +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); + +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); + +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + +ROLLBACK; + +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; + +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; + +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; + +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; + +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; + +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); + +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; + +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); + +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ROLLBACK; + +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; + +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; + +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; + +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; + +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; + +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; + +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); + +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +DROP USER IF EXISTS regress_ivm_user; +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; + +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); + +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; + +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; + +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; +RESET SESSION AUTHORIZATION; + +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +RESET SESSION AUTHORIZATION; + +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; +ROLLBACK; + +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); + +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; + +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; + +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; + +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; + +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); + +ROLLBACK; + +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ROLLBACK; + +-- cleanup + +DROP TABLE rls_tbl CASCADE; +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; + +DROP TABLE mv_base_b CASCADE; +DROP TABLE mv_base_a CASCADE; -- 2.43.0 --Multipart=_Wed__1_Jul_2026_00_04_01_+0900_OVSy2WWK_9aByzDJ Content-Type: text/x-diff; name="v38-0009-Add-support-for-min-max-aggregates-for-IVM.patch" Content-Disposition: attachment; filename="v38-0009-Add-support-for-min-max-aggregates-for-IVM.patch" Content-Transfer-Encoding: 7bit ^ permalink raw reply [nested|flat] 78+ messages in thread
* [PATCH v38 10/11] Add regression tests for Incremental View Maintenance @ 2026-05-29 09:31 Yugo Nagata <[email protected]> 0 siblings, 0 replies; 78+ messages in thread From: Yugo Nagata @ 2026-05-29 09:31 UTC (permalink / raw) --- .../isolation/expected/ivm-create-insert.out | 285 +++++ .../isolation/expected/ivm-create-insert2.out | 305 +++++ .../isolation/expected/ivm-create-insert3.out | 305 +++++ .../isolation/expected/ivm-insert-insert.out | 497 ++++++++ .../isolation/expected/ivm-insert-insert2.out | 373 ++++++ .../isolation/expected/ivm-insert-insert3.out | 373 ++++++ .../isolation/expected/ivm-refresh-insert.out | 213 ++++ .../expected/ivm-refresh-insert2.out | 191 +++ .../expected/ivm-refresh-insert3.out | 191 +++ src/test/isolation/isolation_schedule | 9 + .../isolation/specs/ivm-create-insert.spec | 47 + .../isolation/specs/ivm-create-insert2.spec | 54 + .../isolation/specs/ivm-create-insert3.spec | 54 + .../isolation/specs/ivm-insert-insert.spec | 62 + .../isolation/specs/ivm-insert-insert2.spec | 62 + .../isolation/specs/ivm-insert-insert3.spec | 62 + .../isolation/specs/ivm-refresh-insert.spec | 46 + .../isolation/specs/ivm-refresh-insert2.spec | 46 + .../isolation/specs/ivm-refresh-insert3.spec | 46 + .../regress/expected/incremental_matview.out | 1100 +++++++++++++++++ src/test/regress/parallel_schedule | 1 + src/test/regress/sql/incremental_matview.sql | 580 +++++++++ 22 files changed, 4902 insertions(+) create mode 100644 src/test/isolation/expected/ivm-create-insert.out create mode 100644 src/test/isolation/expected/ivm-create-insert2.out create mode 100644 src/test/isolation/expected/ivm-create-insert3.out create mode 100644 src/test/isolation/expected/ivm-insert-insert.out create mode 100644 src/test/isolation/expected/ivm-insert-insert2.out create mode 100644 src/test/isolation/expected/ivm-insert-insert3.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert2.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert3.out create mode 100644 src/test/isolation/specs/ivm-create-insert.spec create mode 100644 src/test/isolation/specs/ivm-create-insert2.spec create mode 100644 src/test/isolation/specs/ivm-create-insert3.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert2.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert3.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert2.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert3.spec create mode 100644 src/test/regress/expected/incremental_matview.out create mode 100644 src/test/regress/sql/incremental_matview.sql diff --git a/src/test/isolation/expected/ivm-create-insert.out b/src/test/isolation/expected/ivm-create-insert.out new file mode 100644 index 00000000000..5da00043aba --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert.out @@ -0,0 +1,285 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-create-insert2.out b/src/test/isolation/expected/ivm-create-insert2.out new file mode 100644 index 00000000000..907d892c6d4 --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert2.out @@ -0,0 +1,305 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + diff --git a/src/test/isolation/expected/ivm-create-insert3.out b/src/test/isolation/expected/ivm-create-insert3.out new file mode 100644 index 00000000000..907d892c6d4 --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert3.out @@ -0,0 +1,305 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert.out b/src/test/isolation/expected/ivm-insert-insert.out new file mode 100644 index 00000000000..5ca4cfea677 --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert.out @@ -0,0 +1,497 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; <waiting ...> +step c1: COMMIT; +step update2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; <waiting ...> +step c1: COMMIT; +step update2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; <waiting ...> +step c2: COMMIT; +step update1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; <waiting ...> +step c2: COMMIT; +step update1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); <waiting ...> +step c1: COMMIT; +step insert2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); <waiting ...> +step c1: COMMIT; +step insert2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); <waiting ...> +step c2: COMMIT; +step insert1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); <waiting ...> +step c2: COMMIT; +step insert1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert2.out b/src/test/isolation/expected/ivm-insert-insert2.out new file mode 100644 index 00000000000..e1c66d4de5e --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert2.out @@ -0,0 +1,373 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert3.out b/src/test/isolation/expected/ivm-insert-insert3.out new file mode 100644 index 00000000000..e1c66d4de5e --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert3.out @@ -0,0 +1,373 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert.out b/src/test/isolation/expected/ivm-refresh-insert.out new file mode 100644 index 00000000000..a925938bf1c --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert.out @@ -0,0 +1,213 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert2.out b/src/test/isolation/expected/ivm-refresh-insert2.out new file mode 100644 index 00000000000..dc1b16ae34e --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert2.out @@ -0,0 +1,191 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert3.out b/src/test/isolation/expected/ivm-refresh-insert3.out new file mode 100644 index 00000000000..dc1b16ae34e --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert3.out @@ -0,0 +1,191 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/isolation_schedule b/src/test/isolation/isolation_schedule index b8ebe92553c..6b7e873b370 100644 --- a/src/test/isolation/isolation_schedule +++ b/src/test/isolation/isolation_schedule @@ -128,3 +128,12 @@ test: matview-write-skew test: lock-nowait test: for-portion-of test: ddl-dependency-locking +test: ivm-create-insert +test: ivm-create-insert2 +test: ivm-create-insert3 +test: ivm-insert-insert +test: ivm-insert-insert2 +test: ivm-insert-insert3 +test: ivm-refresh-insert +test: ivm-refresh-insert2 +test: ivm-refresh-insert3 diff --git a/src/test/isolation/specs/ivm-create-insert.spec b/src/test/isolation/specs/ivm-create-insert.spec new file mode 100644 index 00000000000..ccd6fd080a9 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert.spec @@ -0,0 +1,47 @@ +# Test interaction between concurrent transactions performing +# create and insert in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-create-insert2.spec b/src/test/isolation/specs/ivm-create-insert2.spec new file mode 100644 index 00000000000..02cec85ae07 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert2.spec @@ -0,0 +1,54 @@ +# Test interaction between concurrent transactions performing +# create and insert in REPEATABLE READ isolation level +# +# Note: +# In this isolation level, it is possible that create_immv could +# create an inconsistent view not including effects of a concurrent +# transaction. So, an warning message is raised to suggest using it +# in READ COMMITTED or executing refresh_immv to make sure to +# make the view contents consistent. + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-create-insert3.spec b/src/test/isolation/specs/ivm-create-insert3.spec new file mode 100644 index 00000000000..19ce03185a4 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert3.spec @@ -0,0 +1,54 @@ +# Test interaction between concurrent transactions performing +# create and insert in SERIALIZABLE isolation level +# +# Note: +# In this isolation level, it is possible that create_immv could +# create an inconsistent view not including effects of a concurrent +# transaction. So, an warning message is raised to suggest using it +# in READ COMMITTED or executing refresh_immv to make sure to +# make the view contents consistent. + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert.spec b/src/test/isolation/specs/ivm-insert-insert.spec new file mode 100644 index 00000000000..b8f794ca191 --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert2.spec b/src/test/isolation/specs/ivm-insert-insert2.spec new file mode 100644 index 00000000000..ed086d1ba1e --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert2.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in REPEATABLE READ isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert3.spec b/src/test/isolation/specs/ivm-insert-insert3.spec new file mode 100644 index 00000000000..b18bd121033 --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert3.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in SERIALIZABLE isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert.spec b/src/test/isolation/specs/ivm-refresh-insert.spec new file mode 100644 index 00000000000..d7181251962 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert2.spec b/src/test/isolation/specs/ivm-refresh-insert2.spec new file mode 100644 index 00000000000..f2d1d5013f2 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert2.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in REPEATABLE READ isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert3.spec b/src/test/isolation/specs/ivm-refresh-insert3.spec new file mode 100644 index 00000000000..0ec2b1d1de0 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert3.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in SERIALIZABLE isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/regress/expected/incremental_matview.out b/src/test/regress/expected/incremental_matview.out new file mode 100644 index 00000000000..f215aa88e48 --- /dev/null +++ b/src/test/regress/expected/incremental_matview.out @@ -0,0 +1,1100 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ERROR: materialized view "mv_ivm_1" has not been populated +HINT: Use the REFRESH MATERIALIZED VIEW command. +REFRESH MATERIALIZED VIEW mv_ivm_1; +NOTICE: could not create an index on materialized view "mv_ivm_1" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 17 +(1 row) + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 1 +(1 row) + +ROLLBACK; +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_rename_index" on materialized view "mv_ivm_rename" +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +ERROR: IVM column can not be renamed +DROP MATERIALIZED VIEW mv_ivm_rename; +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_unique_index" on materialized view "mv_ivm_unique" +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +ERROR: unique index creation on IVM columns is not supported +DROP MATERIALIZED VIEW mv_ivm_unique; +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +NOTICE: could not create an index on materialized view "mv_ivm_func" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +NOTICE: could not create an index on materialized view "mv_ivm_no_tbl" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_duplicate" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +NOTICE: created index "mv_ivm_distinct_index" on materialized view "mv_ivm_distinct" +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 20 + 30 + 40 + 50 +(6 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +ROLLBACK; +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 120 | 2 | 60.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+---------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 220 | 2 | 110.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 20 | 1 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 120 | 2 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; + sum | count +-----+------- +(0 rows) + +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; + i | sum | count +---+-----+------- +(0 rows) + +ROLLBACK; +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 150 | 5 | 30.0000000000000000 +(1 row) + +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 210 | 6 | 35.0000000000000000 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +NOTICE: created index "mv_ivm_avg_bug_index" on materialized view "mv_ivm_avg_bug" +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 3 | 3.3333333333333333 + 2 | 80 | 3 | 26.6666666666666667 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_min_max_index" on materialized view "mv_ivm_min_max" +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 10 + 2 | 20 | 20 + 3 | 30 | 30 + 4 | 40 | 40 + 5 | 50 | 50 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 12 + 2 | 20 | 22 + 3 | 30 | 32 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 11 | 12 + 2 | 20 | 22 + 3 | 30 | 31 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min_max" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 50 +(1 row) + +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 0 | 70 +(1 row) + +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 60 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + | +(1 row) + +ROLLBACK; +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min; + min +----- + 10 +(1 row) + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + min +----- + 20 +(1 row) + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; + min +----- + 30 +(1 row) + +ROLLBACK; +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | sum +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | b +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ERROR: too many column names were specified +ROLLBACK; +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +NOTICE: could not create an index on materialized view "mv_self" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +----+---- + 10 | 10 + 20 | 20 + 30 | 30 +(3 rows) + +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 30 | 30 + 40 | 40 + 200 | 200 +(3 rows) + +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 130 | 130 + 300 | 300 +(4 rows) + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 70 | 70 + 70 | 77 + 77 | 70 + 77 | 77 + 130 | 130 + 300 | 300 +(8 rows) + +ROLLBACK; +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY v1; + v1 | v2 +----+----- + 10 | 100 + 20 | 200 + 30 | 300 +(3 rows) + +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv ORDER BY v1; + v1 | v2 +------+----- + 10 | 100 + 11 | 100 + 1020 | 200 + 1020 | 222 +(4 rows) + +ROLLBACK; +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +NOTICE: created index "mv_ri_index" on materialized view "mv_ri" +SELECT * FROM mv_ri ORDER BY i1; + i1 | i2 +----+---- + 1 | 1 + 2 | 2 + 3 | 3 +(3 rows) + +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; + i1 | i2 +----+---- + 3 | 3 + 10 | 10 +(2 rows) + +ROLLBACK; +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | +(2 rows) + +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | 20 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i +--- +(0 rows) + +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; + i +--- + 1 + +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 30 + | 3 +(2 rows) + +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 300 + | 30 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 1 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 4 +(1 row) + +ROLLBACK; +-- IMMV containing user defined type +BEGIN; +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: return type mytype is only a shell +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: argument type mytype is only a shell +LINE 1: CREATE FUNCTION mytype_out(mytype) + ^ +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +NOTICE: could not create an index on materialized view "mv_mytype" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + x +--- + 1 +(1 row) + +ROLLBACK; +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +ERROR: OUTER JOIN is not supported on incrementally maintainable materialized view +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +ERROR: CTE is not supported on incrementally maintainable materialized view +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +ERROR: ORDER BY clause is not supported on incrementally maintainable materialized view +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; +ERROR: HAVING clause is not supported on incrementally maintainable materialized view +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; +ERROR: mutable function is not supported on incrementally maintainable materialized view +HINT: functions must be marked IMMUTABLE +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; +ERROR: LIMIT/OFFSET clause is not supported on incrementally maintainable materialized view +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; +ERROR: DISTINCT ON is not supported on incrementally maintainable materialized view +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); +ERROR: TABLESAMPLE clause is not supported on incrementally maintainable materialized view +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; +ERROR: window functions are not supported on incrementally maintainable materialized view +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +ERROR: aggregate function with FILTER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +ERROR: aggregate function with DISTINCT arguments is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +ERROR: aggregate function with ORDER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); +ERROR: GROUPING SETS, ROLLUP, or CUBE clauses is not supported on incrementally maintainable materialized view +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ERROR: inheritance parent is not supported on incrementally maintainable materialized view +ROLLBACK; +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; +ERROR: UNION/INTERSECT/EXCEPT statements are not supported on incrementally maintainable materialized view +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; +ERROR: empty target list is not supported on incrementally maintainable materialized view +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; +ERROR: FOR UPDATE/SHARE clause is not supported on incrementally maintainable materialized view +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; +ERROR: column name __ivm_count__ is not supported on incrementally maintainable materialized view +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; +ERROR: GROUP BY expression not appearing in select list is not supported on incrementally maintainable materialized view +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); +ERROR: VALUES is not supported on incrementally maintainable materialized view +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +NOTICE: role "regress_ivm_admin" does not exist, skipping +DROP USER IF EXISTS regress_ivm_user; +NOTICE: role "regress_ivm_user" does not exist, skipping +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +NOTICE: could not create an index on materialized view "ivm_rls" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user +(1 row) + +RESET SESSION AUTHORIZATION; +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user + 3 | baz | regress_ivm_user +(2 rows) + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +-- +(1 row) + +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+-------+------------------ + 2 | bar | regress_ivm_user + 3 | baz | regress_ivm_user + 6 | corge | regress_ivm_user +(3 rows) + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +NOTICE: could not create an index on materialized view "ivm_rls2" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +RESET SESSION AUTHORIZATION; +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +-- +(1 row) + +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + id | data | owner | num +----+-------+------------------+--------- + 2 | bar | regress_ivm_user | two + 3 | baz_2 | regress_ivm_user | three_2 + 6 | corge | regress_ivm_user | six +(3 rows) + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +NOTICE: could not create an index on materialized view "mv_update_same" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + i +--- + 2 +(1 row) + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +NOTICE: created index "mv_self_ref_index" on materialized view "mv_self_ref" +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; + a | b +----+---- + 11 | + 12 | 11 + 13 | 12 +(3 rows) + +ROLLBACK; +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; +NOTICE: created index "mv_idx1_index" on materialized view "mv_idx1" +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; +NOTICE: created index "mv_idx2_index" on materialized view "mv_idx2" +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; +NOTICE: created index "mv_idx3_index" on materialized view "mv_idx3" +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +NOTICE: could not create an index on materialized view "mv_idx4" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; +NOTICE: could not create an index on materialized view "mv_idx5" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); +NOTICE: could not create an index on materialized view "mv_idx6" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ERROR: data type json has no default operator class for access method "btree" +ROLLBACK; +-- cleanup +DROP TABLE rls_tbl CASCADE; +NOTICE: drop cascades to 2 other objects +DETAIL: drop cascades to materialized view ivm_rls +drop cascades to materialized view ivm_rls2 +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; +DROP TABLE mv_base_b CASCADE; +NOTICE: drop cascades to 3 other objects +DETAIL: drop cascades to materialized view mv_ivm_1 +drop cascades to view b_view +drop cascades to materialized view b_mview +DROP TABLE mv_base_a CASCADE; diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index 8fa0a6c47fb..7caca5f64fd 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -77,6 +77,7 @@ test: brin_bloom brin_multi # Another group of parallel tests # ---------- test: create_table_like alter_generic alter_operator misc async dbsize merge misc_functions nls sysviews tsrf tid tidscan tidrangescan collate.utf8 collate.icu.utf8 incremental_sort create_role without_overlaps generated_virtual +test: incremental_matview # collate.linux.utf8 and collate.icu.utf8 tests cannot be run in parallel with each other # psql depends on create_am diff --git a/src/test/regress/sql/incremental_matview.sql b/src/test/regress/sql/incremental_matview.sql new file mode 100644 index 00000000000..2d55c393d6f --- /dev/null +++ b/src/test/regress/sql/incremental_matview.sql @@ -0,0 +1,580 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); + +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +REFRESH MATERIALIZED VIEW mv_ivm_1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; + +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; +ROLLBACK; + +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +DROP MATERIALIZED VIEW mv_ivm_rename; + +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +DROP MATERIALIZED VIEW mv_ivm_unique; + +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; + + +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +ROLLBACK; + +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +ROLLBACK; + +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +ROLLBACK; + +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +ROLLBACK; + +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +ROLLBACK; + +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min; + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); + +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; +ROLLBACK; + +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +SELECT * FROM mv_self ORDER BY v1; +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; +SELECT * FROM mv_self ORDER BY v1; + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + +ROLLBACK; + +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +SELECT * FROM mv ORDER BY v1; +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; +SELECT * FROM mv ORDER BY v1; +ROLLBACK; + +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +SELECT * FROM mv_ri ORDER BY i1; +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; +ROLLBACK; + +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +-- IMMV containing user defined type +BEGIN; + +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); + +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; + +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); + +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); + +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + +ROLLBACK; + +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; + +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; + +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; + +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; + +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; + +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); + +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; + +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); + +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ROLLBACK; + +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; + +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; + +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; + +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; + +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; + +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; + +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); + +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +DROP USER IF EXISTS regress_ivm_user; +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; + +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); + +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; + +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; + +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; +RESET SESSION AUTHORIZATION; + +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +RESET SESSION AUTHORIZATION; + +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; +ROLLBACK; + +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); + +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; + +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; + +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; + +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; + +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); + +ROLLBACK; + +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ROLLBACK; + +-- cleanup + +DROP TABLE rls_tbl CASCADE; +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; + +DROP TABLE mv_base_b CASCADE; +DROP TABLE mv_base_a CASCADE; -- 2.43.0 --Multipart=_Wed__1_Jul_2026_00_04_01_+0900_OVSy2WWK_9aByzDJ Content-Type: text/x-diff; name="v38-0009-Add-support-for-min-max-aggregates-for-IVM.patch" Content-Disposition: attachment; filename="v38-0009-Add-support-for-min-max-aggregates-for-IVM.patch" Content-Transfer-Encoding: 7bit ^ permalink raw reply [nested|flat] 78+ messages in thread
* [PATCH v37 10/11] Add regression tests for Incremental View Maintenance @ 2026-05-29 09:31 Yugo Nagata <[email protected]> 0 siblings, 0 replies; 78+ messages in thread From: Yugo Nagata @ 2026-05-29 09:31 UTC (permalink / raw) --- src/test/isolation/isolation_schedule | 9 + .../regress/expected/incremental_matview.out | 1100 +++++++++++++++++ src/test/regress/parallel_schedule | 1 + src/test/regress/sql/incremental_matview.sql | 580 +++++++++ 4 files changed, 1690 insertions(+) create mode 100644 src/test/regress/expected/incremental_matview.out create mode 100644 src/test/regress/sql/incremental_matview.sql diff --git a/src/test/isolation/isolation_schedule b/src/test/isolation/isolation_schedule index 15c33fad4c5..111fd465207 100644 --- a/src/test/isolation/isolation_schedule +++ b/src/test/isolation/isolation_schedule @@ -127,3 +127,12 @@ test: matview-write-skew test: lock-nowait test: for-portion-of test: ddl-dependency-locking +test: ivm-create-insert +test: ivm-create-insert2 +test: ivm-create-insert3 +test: ivm-insert-insert +test: ivm-insert-insert2 +test: ivm-insert-insert3 +test: ivm-refresh-insert +test: ivm-refresh-insert2 +test: ivm-refresh-insert3 diff --git a/src/test/regress/expected/incremental_matview.out b/src/test/regress/expected/incremental_matview.out new file mode 100644 index 00000000000..f215aa88e48 --- /dev/null +++ b/src/test/regress/expected/incremental_matview.out @@ -0,0 +1,1100 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ERROR: materialized view "mv_ivm_1" has not been populated +HINT: Use the REFRESH MATERIALIZED VIEW command. +REFRESH MATERIALIZED VIEW mv_ivm_1; +NOTICE: could not create an index on materialized view "mv_ivm_1" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 17 +(1 row) + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 1 +(1 row) + +ROLLBACK; +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_rename_index" on materialized view "mv_ivm_rename" +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +ERROR: IVM column can not be renamed +DROP MATERIALIZED VIEW mv_ivm_rename; +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_unique_index" on materialized view "mv_ivm_unique" +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +ERROR: unique index creation on IVM columns is not supported +DROP MATERIALIZED VIEW mv_ivm_unique; +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +NOTICE: could not create an index on materialized view "mv_ivm_func" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +NOTICE: could not create an index on materialized view "mv_ivm_no_tbl" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_duplicate" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +NOTICE: created index "mv_ivm_distinct_index" on materialized view "mv_ivm_distinct" +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 20 + 30 + 40 + 50 +(6 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +ROLLBACK; +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 120 | 2 | 60.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+---------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 220 | 2 | 110.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 20 | 1 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 120 | 2 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; + sum | count +-----+------- +(0 rows) + +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; + i | sum | count +---+-----+------- +(0 rows) + +ROLLBACK; +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 150 | 5 | 30.0000000000000000 +(1 row) + +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 210 | 6 | 35.0000000000000000 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +NOTICE: created index "mv_ivm_avg_bug_index" on materialized view "mv_ivm_avg_bug" +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 3 | 3.3333333333333333 + 2 | 80 | 3 | 26.6666666666666667 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_min_max_index" on materialized view "mv_ivm_min_max" +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 10 + 2 | 20 | 20 + 3 | 30 | 30 + 4 | 40 | 40 + 5 | 50 | 50 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 12 + 2 | 20 | 22 + 3 | 30 | 32 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 11 | 12 + 2 | 20 | 22 + 3 | 30 | 31 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min_max" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 50 +(1 row) + +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 0 | 70 +(1 row) + +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 60 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + | +(1 row) + +ROLLBACK; +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min; + min +----- + 10 +(1 row) + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + min +----- + 20 +(1 row) + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; + min +----- + 30 +(1 row) + +ROLLBACK; +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | sum +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | b +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ERROR: too many column names were specified +ROLLBACK; +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +NOTICE: could not create an index on materialized view "mv_self" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +----+---- + 10 | 10 + 20 | 20 + 30 | 30 +(3 rows) + +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 30 | 30 + 40 | 40 + 200 | 200 +(3 rows) + +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 130 | 130 + 300 | 300 +(4 rows) + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 70 | 70 + 70 | 77 + 77 | 70 + 77 | 77 + 130 | 130 + 300 | 300 +(8 rows) + +ROLLBACK; +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY v1; + v1 | v2 +----+----- + 10 | 100 + 20 | 200 + 30 | 300 +(3 rows) + +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv ORDER BY v1; + v1 | v2 +------+----- + 10 | 100 + 11 | 100 + 1020 | 200 + 1020 | 222 +(4 rows) + +ROLLBACK; +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +NOTICE: created index "mv_ri_index" on materialized view "mv_ri" +SELECT * FROM mv_ri ORDER BY i1; + i1 | i2 +----+---- + 1 | 1 + 2 | 2 + 3 | 3 +(3 rows) + +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; + i1 | i2 +----+---- + 3 | 3 + 10 | 10 +(2 rows) + +ROLLBACK; +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | +(2 rows) + +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | 20 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i +--- +(0 rows) + +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; + i +--- + 1 + +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 30 + | 3 +(2 rows) + +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 300 + | 30 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 1 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 4 +(1 row) + +ROLLBACK; +-- IMMV containing user defined type +BEGIN; +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: return type mytype is only a shell +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: argument type mytype is only a shell +LINE 1: CREATE FUNCTION mytype_out(mytype) + ^ +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +NOTICE: could not create an index on materialized view "mv_mytype" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + x +--- + 1 +(1 row) + +ROLLBACK; +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +ERROR: OUTER JOIN is not supported on incrementally maintainable materialized view +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +ERROR: CTE is not supported on incrementally maintainable materialized view +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +ERROR: ORDER BY clause is not supported on incrementally maintainable materialized view +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; +ERROR: HAVING clause is not supported on incrementally maintainable materialized view +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; +ERROR: mutable function is not supported on incrementally maintainable materialized view +HINT: functions must be marked IMMUTABLE +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; +ERROR: LIMIT/OFFSET clause is not supported on incrementally maintainable materialized view +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; +ERROR: DISTINCT ON is not supported on incrementally maintainable materialized view +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); +ERROR: TABLESAMPLE clause is not supported on incrementally maintainable materialized view +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; +ERROR: window functions are not supported on incrementally maintainable materialized view +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +ERROR: aggregate function with FILTER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +ERROR: aggregate function with DISTINCT arguments is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +ERROR: aggregate function with ORDER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); +ERROR: GROUPING SETS, ROLLUP, or CUBE clauses is not supported on incrementally maintainable materialized view +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ERROR: inheritance parent is not supported on incrementally maintainable materialized view +ROLLBACK; +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; +ERROR: UNION/INTERSECT/EXCEPT statements are not supported on incrementally maintainable materialized view +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; +ERROR: empty target list is not supported on incrementally maintainable materialized view +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; +ERROR: FOR UPDATE/SHARE clause is not supported on incrementally maintainable materialized view +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; +ERROR: column name __ivm_count__ is not supported on incrementally maintainable materialized view +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; +ERROR: GROUP BY expression not appearing in select list is not supported on incrementally maintainable materialized view +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); +ERROR: VALUES is not supported on incrementally maintainable materialized view +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +NOTICE: role "regress_ivm_admin" does not exist, skipping +DROP USER IF EXISTS regress_ivm_user; +NOTICE: role "regress_ivm_user" does not exist, skipping +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +NOTICE: could not create an index on materialized view "ivm_rls" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user +(1 row) + +RESET SESSION AUTHORIZATION; +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user + 3 | baz | regress_ivm_user +(2 rows) + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +-- +(1 row) + +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+-------+------------------ + 2 | bar | regress_ivm_user + 3 | baz | regress_ivm_user + 6 | corge | regress_ivm_user +(3 rows) + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +NOTICE: could not create an index on materialized view "ivm_rls2" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +RESET SESSION AUTHORIZATION; +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +-- +(1 row) + +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + id | data | owner | num +----+-------+------------------+--------- + 2 | bar | regress_ivm_user | two + 3 | baz_2 | regress_ivm_user | three_2 + 6 | corge | regress_ivm_user | six +(3 rows) + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +NOTICE: could not create an index on materialized view "mv_update_same" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + i +--- + 2 +(1 row) + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +NOTICE: created index "mv_self_ref_index" on materialized view "mv_self_ref" +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; + a | b +----+---- + 11 | + 12 | 11 + 13 | 12 +(3 rows) + +ROLLBACK; +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; +NOTICE: created index "mv_idx1_index" on materialized view "mv_idx1" +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; +NOTICE: created index "mv_idx2_index" on materialized view "mv_idx2" +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; +NOTICE: created index "mv_idx3_index" on materialized view "mv_idx3" +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +NOTICE: could not create an index on materialized view "mv_idx4" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; +NOTICE: could not create an index on materialized view "mv_idx5" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); +NOTICE: could not create an index on materialized view "mv_idx6" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ERROR: data type json has no default operator class for access method "btree" +ROLLBACK; +-- cleanup +DROP TABLE rls_tbl CASCADE; +NOTICE: drop cascades to 2 other objects +DETAIL: drop cascades to materialized view ivm_rls +drop cascades to materialized view ivm_rls2 +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; +DROP TABLE mv_base_b CASCADE; +NOTICE: drop cascades to 3 other objects +DETAIL: drop cascades to materialized view mv_ivm_1 +drop cascades to view b_view +drop cascades to materialized view b_mview +DROP TABLE mv_base_a CASCADE; diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index 8fa0a6c47fb..7caca5f64fd 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -77,6 +77,7 @@ test: brin_bloom brin_multi # Another group of parallel tests # ---------- test: create_table_like alter_generic alter_operator misc async dbsize merge misc_functions nls sysviews tsrf tid tidscan tidrangescan collate.utf8 collate.icu.utf8 incremental_sort create_role without_overlaps generated_virtual +test: incremental_matview # collate.linux.utf8 and collate.icu.utf8 tests cannot be run in parallel with each other # psql depends on create_am diff --git a/src/test/regress/sql/incremental_matview.sql b/src/test/regress/sql/incremental_matview.sql new file mode 100644 index 00000000000..2d55c393d6f --- /dev/null +++ b/src/test/regress/sql/incremental_matview.sql @@ -0,0 +1,580 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); + +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +REFRESH MATERIALIZED VIEW mv_ivm_1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; + +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; +ROLLBACK; + +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +DROP MATERIALIZED VIEW mv_ivm_rename; + +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +DROP MATERIALIZED VIEW mv_ivm_unique; + +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; + + +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +ROLLBACK; + +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +ROLLBACK; + +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +ROLLBACK; + +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +ROLLBACK; + +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +ROLLBACK; + +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min; + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); + +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; +ROLLBACK; + +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +SELECT * FROM mv_self ORDER BY v1; +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; +SELECT * FROM mv_self ORDER BY v1; + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + +ROLLBACK; + +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +SELECT * FROM mv ORDER BY v1; +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; +SELECT * FROM mv ORDER BY v1; +ROLLBACK; + +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +SELECT * FROM mv_ri ORDER BY i1; +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; +ROLLBACK; + +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +-- IMMV containing user defined type +BEGIN; + +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); + +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; + +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); + +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); + +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + +ROLLBACK; + +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; + +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; + +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; + +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; + +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; + +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); + +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; + +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); + +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ROLLBACK; + +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; + +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; + +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; + +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; + +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; + +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; + +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); + +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +DROP USER IF EXISTS regress_ivm_user; +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; + +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); + +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; + +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; + +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; +RESET SESSION AUTHORIZATION; + +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +RESET SESSION AUTHORIZATION; + +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; +ROLLBACK; + +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); + +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; + +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; + +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; + +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; + +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); + +ROLLBACK; + +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ROLLBACK; + +-- cleanup + +DROP TABLE rls_tbl CASCADE; +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; + +DROP TABLE mv_base_b CASCADE; +DROP TABLE mv_base_a CASCADE; -- 2.43.0 --Multipart=_Fri__29_May_2026_23_14_17_+0900_Te0o73X2VqYK57Gd Content-Type: text/x-diff; name="v37-0009-Add-support-for-min-max-aggregates-for-IVM.patch" Content-Disposition: attachment; filename="v37-0009-Add-support-for-min-max-aggregates-for-IVM.patch" Content-Transfer-Encoding: 7bit ^ permalink raw reply [nested|flat] 78+ messages in thread
* [PATCH v38 10/11] Add regression tests for Incremental View Maintenance @ 2026-05-29 09:31 Yugo Nagata <[email protected]> 0 siblings, 0 replies; 78+ messages in thread From: Yugo Nagata @ 2026-05-29 09:31 UTC (permalink / raw) --- .../isolation/expected/ivm-create-insert.out | 285 +++++ .../isolation/expected/ivm-create-insert2.out | 305 +++++ .../isolation/expected/ivm-create-insert3.out | 305 +++++ .../isolation/expected/ivm-insert-insert.out | 497 ++++++++ .../isolation/expected/ivm-insert-insert2.out | 373 ++++++ .../isolation/expected/ivm-insert-insert3.out | 373 ++++++ .../isolation/expected/ivm-refresh-insert.out | 213 ++++ .../expected/ivm-refresh-insert2.out | 191 +++ .../expected/ivm-refresh-insert3.out | 191 +++ src/test/isolation/isolation_schedule | 9 + .../isolation/specs/ivm-create-insert.spec | 47 + .../isolation/specs/ivm-create-insert2.spec | 54 + .../isolation/specs/ivm-create-insert3.spec | 54 + .../isolation/specs/ivm-insert-insert.spec | 62 + .../isolation/specs/ivm-insert-insert2.spec | 62 + .../isolation/specs/ivm-insert-insert3.spec | 62 + .../isolation/specs/ivm-refresh-insert.spec | 46 + .../isolation/specs/ivm-refresh-insert2.spec | 46 + .../isolation/specs/ivm-refresh-insert3.spec | 46 + .../regress/expected/incremental_matview.out | 1100 +++++++++++++++++ src/test/regress/parallel_schedule | 1 + src/test/regress/sql/incremental_matview.sql | 580 +++++++++ 22 files changed, 4902 insertions(+) create mode 100644 src/test/isolation/expected/ivm-create-insert.out create mode 100644 src/test/isolation/expected/ivm-create-insert2.out create mode 100644 src/test/isolation/expected/ivm-create-insert3.out create mode 100644 src/test/isolation/expected/ivm-insert-insert.out create mode 100644 src/test/isolation/expected/ivm-insert-insert2.out create mode 100644 src/test/isolation/expected/ivm-insert-insert3.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert2.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert3.out create mode 100644 src/test/isolation/specs/ivm-create-insert.spec create mode 100644 src/test/isolation/specs/ivm-create-insert2.spec create mode 100644 src/test/isolation/specs/ivm-create-insert3.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert2.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert3.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert2.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert3.spec create mode 100644 src/test/regress/expected/incremental_matview.out create mode 100644 src/test/regress/sql/incremental_matview.sql diff --git a/src/test/isolation/expected/ivm-create-insert.out b/src/test/isolation/expected/ivm-create-insert.out new file mode 100644 index 00000000000..5da00043aba --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert.out @@ -0,0 +1,285 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-create-insert2.out b/src/test/isolation/expected/ivm-create-insert2.out new file mode 100644 index 00000000000..907d892c6d4 --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert2.out @@ -0,0 +1,305 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + diff --git a/src/test/isolation/expected/ivm-create-insert3.out b/src/test/isolation/expected/ivm-create-insert3.out new file mode 100644 index 00000000000..907d892c6d4 --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert3.out @@ -0,0 +1,305 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert.out b/src/test/isolation/expected/ivm-insert-insert.out new file mode 100644 index 00000000000..5ca4cfea677 --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert.out @@ -0,0 +1,497 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; <waiting ...> +step c1: COMMIT; +step update2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; <waiting ...> +step c1: COMMIT; +step update2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; <waiting ...> +step c2: COMMIT; +step update1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; <waiting ...> +step c2: COMMIT; +step update1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); <waiting ...> +step c1: COMMIT; +step insert2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); <waiting ...> +step c1: COMMIT; +step insert2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); <waiting ...> +step c2: COMMIT; +step insert1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); <waiting ...> +step c2: COMMIT; +step insert1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert2.out b/src/test/isolation/expected/ivm-insert-insert2.out new file mode 100644 index 00000000000..e1c66d4de5e --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert2.out @@ -0,0 +1,373 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert3.out b/src/test/isolation/expected/ivm-insert-insert3.out new file mode 100644 index 00000000000..e1c66d4de5e --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert3.out @@ -0,0 +1,373 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert.out b/src/test/isolation/expected/ivm-refresh-insert.out new file mode 100644 index 00000000000..a925938bf1c --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert.out @@ -0,0 +1,213 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert2.out b/src/test/isolation/expected/ivm-refresh-insert2.out new file mode 100644 index 00000000000..dc1b16ae34e --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert2.out @@ -0,0 +1,191 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert3.out b/src/test/isolation/expected/ivm-refresh-insert3.out new file mode 100644 index 00000000000..dc1b16ae34e --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert3.out @@ -0,0 +1,191 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/isolation_schedule b/src/test/isolation/isolation_schedule index b8ebe92553c..6b7e873b370 100644 --- a/src/test/isolation/isolation_schedule +++ b/src/test/isolation/isolation_schedule @@ -128,3 +128,12 @@ test: matview-write-skew test: lock-nowait test: for-portion-of test: ddl-dependency-locking +test: ivm-create-insert +test: ivm-create-insert2 +test: ivm-create-insert3 +test: ivm-insert-insert +test: ivm-insert-insert2 +test: ivm-insert-insert3 +test: ivm-refresh-insert +test: ivm-refresh-insert2 +test: ivm-refresh-insert3 diff --git a/src/test/isolation/specs/ivm-create-insert.spec b/src/test/isolation/specs/ivm-create-insert.spec new file mode 100644 index 00000000000..ccd6fd080a9 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert.spec @@ -0,0 +1,47 @@ +# Test interaction between concurrent transactions performing +# create and insert in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-create-insert2.spec b/src/test/isolation/specs/ivm-create-insert2.spec new file mode 100644 index 00000000000..02cec85ae07 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert2.spec @@ -0,0 +1,54 @@ +# Test interaction between concurrent transactions performing +# create and insert in REPEATABLE READ isolation level +# +# Note: +# In this isolation level, it is possible that create_immv could +# create an inconsistent view not including effects of a concurrent +# transaction. So, an warning message is raised to suggest using it +# in READ COMMITTED or executing refresh_immv to make sure to +# make the view contents consistent. + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-create-insert3.spec b/src/test/isolation/specs/ivm-create-insert3.spec new file mode 100644 index 00000000000..19ce03185a4 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert3.spec @@ -0,0 +1,54 @@ +# Test interaction between concurrent transactions performing +# create and insert in SERIALIZABLE isolation level +# +# Note: +# In this isolation level, it is possible that create_immv could +# create an inconsistent view not including effects of a concurrent +# transaction. So, an warning message is raised to suggest using it +# in READ COMMITTED or executing refresh_immv to make sure to +# make the view contents consistent. + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert.spec b/src/test/isolation/specs/ivm-insert-insert.spec new file mode 100644 index 00000000000..b8f794ca191 --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert2.spec b/src/test/isolation/specs/ivm-insert-insert2.spec new file mode 100644 index 00000000000..ed086d1ba1e --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert2.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in REPEATABLE READ isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert3.spec b/src/test/isolation/specs/ivm-insert-insert3.spec new file mode 100644 index 00000000000..b18bd121033 --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert3.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in SERIALIZABLE isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert.spec b/src/test/isolation/specs/ivm-refresh-insert.spec new file mode 100644 index 00000000000..d7181251962 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert2.spec b/src/test/isolation/specs/ivm-refresh-insert2.spec new file mode 100644 index 00000000000..f2d1d5013f2 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert2.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in REPEATABLE READ isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert3.spec b/src/test/isolation/specs/ivm-refresh-insert3.spec new file mode 100644 index 00000000000..0ec2b1d1de0 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert3.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in SERIALIZABLE isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/regress/expected/incremental_matview.out b/src/test/regress/expected/incremental_matview.out new file mode 100644 index 00000000000..f215aa88e48 --- /dev/null +++ b/src/test/regress/expected/incremental_matview.out @@ -0,0 +1,1100 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ERROR: materialized view "mv_ivm_1" has not been populated +HINT: Use the REFRESH MATERIALIZED VIEW command. +REFRESH MATERIALIZED VIEW mv_ivm_1; +NOTICE: could not create an index on materialized view "mv_ivm_1" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 17 +(1 row) + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 1 +(1 row) + +ROLLBACK; +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_rename_index" on materialized view "mv_ivm_rename" +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +ERROR: IVM column can not be renamed +DROP MATERIALIZED VIEW mv_ivm_rename; +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_unique_index" on materialized view "mv_ivm_unique" +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +ERROR: unique index creation on IVM columns is not supported +DROP MATERIALIZED VIEW mv_ivm_unique; +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +NOTICE: could not create an index on materialized view "mv_ivm_func" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +NOTICE: could not create an index on materialized view "mv_ivm_no_tbl" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_duplicate" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +NOTICE: created index "mv_ivm_distinct_index" on materialized view "mv_ivm_distinct" +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 20 + 30 + 40 + 50 +(6 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +ROLLBACK; +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 120 | 2 | 60.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+---------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 220 | 2 | 110.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 20 | 1 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 120 | 2 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; + sum | count +-----+------- +(0 rows) + +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; + i | sum | count +---+-----+------- +(0 rows) + +ROLLBACK; +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 150 | 5 | 30.0000000000000000 +(1 row) + +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 210 | 6 | 35.0000000000000000 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +NOTICE: created index "mv_ivm_avg_bug_index" on materialized view "mv_ivm_avg_bug" +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 3 | 3.3333333333333333 + 2 | 80 | 3 | 26.6666666666666667 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_min_max_index" on materialized view "mv_ivm_min_max" +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 10 + 2 | 20 | 20 + 3 | 30 | 30 + 4 | 40 | 40 + 5 | 50 | 50 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 12 + 2 | 20 | 22 + 3 | 30 | 32 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 11 | 12 + 2 | 20 | 22 + 3 | 30 | 31 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min_max" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 50 +(1 row) + +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 0 | 70 +(1 row) + +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 60 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + | +(1 row) + +ROLLBACK; +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min; + min +----- + 10 +(1 row) + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + min +----- + 20 +(1 row) + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; + min +----- + 30 +(1 row) + +ROLLBACK; +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | sum +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | b +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ERROR: too many column names were specified +ROLLBACK; +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +NOTICE: could not create an index on materialized view "mv_self" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +----+---- + 10 | 10 + 20 | 20 + 30 | 30 +(3 rows) + +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 30 | 30 + 40 | 40 + 200 | 200 +(3 rows) + +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 130 | 130 + 300 | 300 +(4 rows) + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 70 | 70 + 70 | 77 + 77 | 70 + 77 | 77 + 130 | 130 + 300 | 300 +(8 rows) + +ROLLBACK; +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY v1; + v1 | v2 +----+----- + 10 | 100 + 20 | 200 + 30 | 300 +(3 rows) + +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv ORDER BY v1; + v1 | v2 +------+----- + 10 | 100 + 11 | 100 + 1020 | 200 + 1020 | 222 +(4 rows) + +ROLLBACK; +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +NOTICE: created index "mv_ri_index" on materialized view "mv_ri" +SELECT * FROM mv_ri ORDER BY i1; + i1 | i2 +----+---- + 1 | 1 + 2 | 2 + 3 | 3 +(3 rows) + +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; + i1 | i2 +----+---- + 3 | 3 + 10 | 10 +(2 rows) + +ROLLBACK; +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | +(2 rows) + +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | 20 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i +--- +(0 rows) + +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; + i +--- + 1 + +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 30 + | 3 +(2 rows) + +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 300 + | 30 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 1 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 4 +(1 row) + +ROLLBACK; +-- IMMV containing user defined type +BEGIN; +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: return type mytype is only a shell +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: argument type mytype is only a shell +LINE 1: CREATE FUNCTION mytype_out(mytype) + ^ +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +NOTICE: could not create an index on materialized view "mv_mytype" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + x +--- + 1 +(1 row) + +ROLLBACK; +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +ERROR: OUTER JOIN is not supported on incrementally maintainable materialized view +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +ERROR: CTE is not supported on incrementally maintainable materialized view +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +ERROR: ORDER BY clause is not supported on incrementally maintainable materialized view +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; +ERROR: HAVING clause is not supported on incrementally maintainable materialized view +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; +ERROR: mutable function is not supported on incrementally maintainable materialized view +HINT: functions must be marked IMMUTABLE +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; +ERROR: LIMIT/OFFSET clause is not supported on incrementally maintainable materialized view +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; +ERROR: DISTINCT ON is not supported on incrementally maintainable materialized view +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); +ERROR: TABLESAMPLE clause is not supported on incrementally maintainable materialized view +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; +ERROR: window functions are not supported on incrementally maintainable materialized view +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +ERROR: aggregate function with FILTER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +ERROR: aggregate function with DISTINCT arguments is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +ERROR: aggregate function with ORDER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); +ERROR: GROUPING SETS, ROLLUP, or CUBE clauses is not supported on incrementally maintainable materialized view +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ERROR: inheritance parent is not supported on incrementally maintainable materialized view +ROLLBACK; +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; +ERROR: UNION/INTERSECT/EXCEPT statements are not supported on incrementally maintainable materialized view +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; +ERROR: empty target list is not supported on incrementally maintainable materialized view +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; +ERROR: FOR UPDATE/SHARE clause is not supported on incrementally maintainable materialized view +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; +ERROR: column name __ivm_count__ is not supported on incrementally maintainable materialized view +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; +ERROR: GROUP BY expression not appearing in select list is not supported on incrementally maintainable materialized view +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); +ERROR: VALUES is not supported on incrementally maintainable materialized view +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +NOTICE: role "regress_ivm_admin" does not exist, skipping +DROP USER IF EXISTS regress_ivm_user; +NOTICE: role "regress_ivm_user" does not exist, skipping +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +NOTICE: could not create an index on materialized view "ivm_rls" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user +(1 row) + +RESET SESSION AUTHORIZATION; +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user + 3 | baz | regress_ivm_user +(2 rows) + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +-- +(1 row) + +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+-------+------------------ + 2 | bar | regress_ivm_user + 3 | baz | regress_ivm_user + 6 | corge | regress_ivm_user +(3 rows) + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +NOTICE: could not create an index on materialized view "ivm_rls2" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +RESET SESSION AUTHORIZATION; +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +-- +(1 row) + +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + id | data | owner | num +----+-------+------------------+--------- + 2 | bar | regress_ivm_user | two + 3 | baz_2 | regress_ivm_user | three_2 + 6 | corge | regress_ivm_user | six +(3 rows) + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +NOTICE: could not create an index on materialized view "mv_update_same" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + i +--- + 2 +(1 row) + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +NOTICE: created index "mv_self_ref_index" on materialized view "mv_self_ref" +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; + a | b +----+---- + 11 | + 12 | 11 + 13 | 12 +(3 rows) + +ROLLBACK; +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; +NOTICE: created index "mv_idx1_index" on materialized view "mv_idx1" +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; +NOTICE: created index "mv_idx2_index" on materialized view "mv_idx2" +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; +NOTICE: created index "mv_idx3_index" on materialized view "mv_idx3" +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +NOTICE: could not create an index on materialized view "mv_idx4" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; +NOTICE: could not create an index on materialized view "mv_idx5" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); +NOTICE: could not create an index on materialized view "mv_idx6" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ERROR: data type json has no default operator class for access method "btree" +ROLLBACK; +-- cleanup +DROP TABLE rls_tbl CASCADE; +NOTICE: drop cascades to 2 other objects +DETAIL: drop cascades to materialized view ivm_rls +drop cascades to materialized view ivm_rls2 +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; +DROP TABLE mv_base_b CASCADE; +NOTICE: drop cascades to 3 other objects +DETAIL: drop cascades to materialized view mv_ivm_1 +drop cascades to view b_view +drop cascades to materialized view b_mview +DROP TABLE mv_base_a CASCADE; diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index 8fa0a6c47fb..7caca5f64fd 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -77,6 +77,7 @@ test: brin_bloom brin_multi # Another group of parallel tests # ---------- test: create_table_like alter_generic alter_operator misc async dbsize merge misc_functions nls sysviews tsrf tid tidscan tidrangescan collate.utf8 collate.icu.utf8 incremental_sort create_role without_overlaps generated_virtual +test: incremental_matview # collate.linux.utf8 and collate.icu.utf8 tests cannot be run in parallel with each other # psql depends on create_am diff --git a/src/test/regress/sql/incremental_matview.sql b/src/test/regress/sql/incremental_matview.sql new file mode 100644 index 00000000000..2d55c393d6f --- /dev/null +++ b/src/test/regress/sql/incremental_matview.sql @@ -0,0 +1,580 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); + +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +REFRESH MATERIALIZED VIEW mv_ivm_1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; + +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; +ROLLBACK; + +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +DROP MATERIALIZED VIEW mv_ivm_rename; + +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +DROP MATERIALIZED VIEW mv_ivm_unique; + +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; + + +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +ROLLBACK; + +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +ROLLBACK; + +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +ROLLBACK; + +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +ROLLBACK; + +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +ROLLBACK; + +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min; + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); + +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; +ROLLBACK; + +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +SELECT * FROM mv_self ORDER BY v1; +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; +SELECT * FROM mv_self ORDER BY v1; + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + +ROLLBACK; + +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +SELECT * FROM mv ORDER BY v1; +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; +SELECT * FROM mv ORDER BY v1; +ROLLBACK; + +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +SELECT * FROM mv_ri ORDER BY i1; +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; +ROLLBACK; + +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +-- IMMV containing user defined type +BEGIN; + +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); + +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; + +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); + +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); + +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + +ROLLBACK; + +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; + +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; + +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; + +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; + +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; + +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); + +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; + +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); + +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ROLLBACK; + +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; + +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; + +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; + +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; + +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; + +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; + +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); + +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +DROP USER IF EXISTS regress_ivm_user; +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; + +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); + +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; + +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; + +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; +RESET SESSION AUTHORIZATION; + +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +RESET SESSION AUTHORIZATION; + +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; +ROLLBACK; + +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); + +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; + +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; + +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; + +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; + +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); + +ROLLBACK; + +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ROLLBACK; + +-- cleanup + +DROP TABLE rls_tbl CASCADE; +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; + +DROP TABLE mv_base_b CASCADE; +DROP TABLE mv_base_a CASCADE; -- 2.43.0 --Multipart=_Wed__1_Jul_2026_00_04_01_+0900_OVSy2WWK_9aByzDJ Content-Type: text/x-diff; name="v38-0009-Add-support-for-min-max-aggregates-for-IVM.patch" Content-Disposition: attachment; filename="v38-0009-Add-support-for-min-max-aggregates-for-IVM.patch" Content-Transfer-Encoding: 7bit ^ permalink raw reply [nested|flat] 78+ messages in thread
* [PATCH v39 7/8] Add regression tests for Incremental View Maintenance @ 2026-05-29 09:31 Yugo Nagata <[email protected]> 0 siblings, 0 replies; 78+ messages in thread From: Yugo Nagata @ 2026-05-29 09:31 UTC (permalink / raw) --- .../isolation/expected/ivm-create-insert.out | 285 ++++++++ .../isolation/expected/ivm-create-insert2.out | 305 ++++++++ .../isolation/expected/ivm-create-insert3.out | 305 ++++++++ .../isolation/expected/ivm-insert-insert.out | 497 +++++++++++++ .../isolation/expected/ivm-insert-insert2.out | 373 ++++++++++ .../isolation/expected/ivm-insert-insert3.out | 373 ++++++++++ .../isolation/expected/ivm-refresh-insert.out | 213 ++++++ .../expected/ivm-refresh-insert2.out | 191 +++++ .../expected/ivm-refresh-insert3.out | 191 +++++ src/test/isolation/isolation_schedule | 9 + .../isolation/specs/ivm-create-insert.spec | 47 ++ .../isolation/specs/ivm-create-insert2.spec | 54 ++ .../isolation/specs/ivm-create-insert3.spec | 54 ++ .../isolation/specs/ivm-insert-insert.spec | 62 ++ .../isolation/specs/ivm-insert-insert2.spec | 62 ++ .../isolation/specs/ivm-insert-insert3.spec | 62 ++ .../isolation/specs/ivm-refresh-insert.spec | 46 ++ .../isolation/specs/ivm-refresh-insert2.spec | 46 ++ .../isolation/specs/ivm-refresh-insert3.spec | 46 ++ .../regress/expected/incremental_matview.out | 667 ++++++++++++++++++ src/test/regress/parallel_schedule | 1 + src/test/regress/sql/incremental_matview.sql | 407 +++++++++++ 22 files changed, 4296 insertions(+) create mode 100644 src/test/isolation/expected/ivm-create-insert.out create mode 100644 src/test/isolation/expected/ivm-create-insert2.out create mode 100644 src/test/isolation/expected/ivm-create-insert3.out create mode 100644 src/test/isolation/expected/ivm-insert-insert.out create mode 100644 src/test/isolation/expected/ivm-insert-insert2.out create mode 100644 src/test/isolation/expected/ivm-insert-insert3.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert2.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert3.out create mode 100644 src/test/isolation/specs/ivm-create-insert.spec create mode 100644 src/test/isolation/specs/ivm-create-insert2.spec create mode 100644 src/test/isolation/specs/ivm-create-insert3.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert2.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert3.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert2.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert3.spec create mode 100644 src/test/regress/expected/incremental_matview.out create mode 100644 src/test/regress/sql/incremental_matview.sql diff --git a/src/test/isolation/expected/ivm-create-insert.out b/src/test/isolation/expected/ivm-create-insert.out new file mode 100644 index 00000000000..5da00043aba --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert.out @@ -0,0 +1,285 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-create-insert2.out b/src/test/isolation/expected/ivm-create-insert2.out new file mode 100644 index 00000000000..907d892c6d4 --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert2.out @@ -0,0 +1,305 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + diff --git a/src/test/isolation/expected/ivm-create-insert3.out b/src/test/isolation/expected/ivm-create-insert3.out new file mode 100644 index 00000000000..907d892c6d4 --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert3.out @@ -0,0 +1,305 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert.out b/src/test/isolation/expected/ivm-insert-insert.out new file mode 100644 index 00000000000..5ca4cfea677 --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert.out @@ -0,0 +1,497 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; <waiting ...> +step c1: COMMIT; +step update2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; <waiting ...> +step c1: COMMIT; +step update2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; <waiting ...> +step c2: COMMIT; +step update1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; <waiting ...> +step c2: COMMIT; +step update1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); <waiting ...> +step c1: COMMIT; +step insert2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); <waiting ...> +step c1: COMMIT; +step insert2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); <waiting ...> +step c2: COMMIT; +step insert1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); <waiting ...> +step c2: COMMIT; +step insert1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert2.out b/src/test/isolation/expected/ivm-insert-insert2.out new file mode 100644 index 00000000000..e1c66d4de5e --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert2.out @@ -0,0 +1,373 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert3.out b/src/test/isolation/expected/ivm-insert-insert3.out new file mode 100644 index 00000000000..e1c66d4de5e --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert3.out @@ -0,0 +1,373 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert.out b/src/test/isolation/expected/ivm-refresh-insert.out new file mode 100644 index 00000000000..a925938bf1c --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert.out @@ -0,0 +1,213 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert2.out b/src/test/isolation/expected/ivm-refresh-insert2.out new file mode 100644 index 00000000000..dc1b16ae34e --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert2.out @@ -0,0 +1,191 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert3.out b/src/test/isolation/expected/ivm-refresh-insert3.out new file mode 100644 index 00000000000..dc1b16ae34e --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert3.out @@ -0,0 +1,191 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/isolation_schedule b/src/test/isolation/isolation_schedule index b8ebe92553c..6b7e873b370 100644 --- a/src/test/isolation/isolation_schedule +++ b/src/test/isolation/isolation_schedule @@ -128,3 +128,12 @@ test: matview-write-skew test: lock-nowait test: for-portion-of test: ddl-dependency-locking +test: ivm-create-insert +test: ivm-create-insert2 +test: ivm-create-insert3 +test: ivm-insert-insert +test: ivm-insert-insert2 +test: ivm-insert-insert3 +test: ivm-refresh-insert +test: ivm-refresh-insert2 +test: ivm-refresh-insert3 diff --git a/src/test/isolation/specs/ivm-create-insert.spec b/src/test/isolation/specs/ivm-create-insert.spec new file mode 100644 index 00000000000..ccd6fd080a9 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert.spec @@ -0,0 +1,47 @@ +# Test interaction between concurrent transactions performing +# create and insert in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-create-insert2.spec b/src/test/isolation/specs/ivm-create-insert2.spec new file mode 100644 index 00000000000..02cec85ae07 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert2.spec @@ -0,0 +1,54 @@ +# Test interaction between concurrent transactions performing +# create and insert in REPEATABLE READ isolation level +# +# Note: +# In this isolation level, it is possible that create_immv could +# create an inconsistent view not including effects of a concurrent +# transaction. So, an warning message is raised to suggest using it +# in READ COMMITTED or executing refresh_immv to make sure to +# make the view contents consistent. + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-create-insert3.spec b/src/test/isolation/specs/ivm-create-insert3.spec new file mode 100644 index 00000000000..19ce03185a4 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert3.spec @@ -0,0 +1,54 @@ +# Test interaction between concurrent transactions performing +# create and insert in SERIALIZABLE isolation level +# +# Note: +# In this isolation level, it is possible that create_immv could +# create an inconsistent view not including effects of a concurrent +# transaction. So, an warning message is raised to suggest using it +# in READ COMMITTED or executing refresh_immv to make sure to +# make the view contents consistent. + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert.spec b/src/test/isolation/specs/ivm-insert-insert.spec new file mode 100644 index 00000000000..b8f794ca191 --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert2.spec b/src/test/isolation/specs/ivm-insert-insert2.spec new file mode 100644 index 00000000000..ed086d1ba1e --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert2.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in REPEATABLE READ isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert3.spec b/src/test/isolation/specs/ivm-insert-insert3.spec new file mode 100644 index 00000000000..b18bd121033 --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert3.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in SERIALIZABLE isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert.spec b/src/test/isolation/specs/ivm-refresh-insert.spec new file mode 100644 index 00000000000..d7181251962 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert2.spec b/src/test/isolation/specs/ivm-refresh-insert2.spec new file mode 100644 index 00000000000..f2d1d5013f2 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert2.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in REPEATABLE READ isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert3.spec b/src/test/isolation/specs/ivm-refresh-insert3.spec new file mode 100644 index 00000000000..0ec2b1d1de0 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert3.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in SERIALIZABLE isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/regress/expected/incremental_matview.out b/src/test/regress/expected/incremental_matview.out new file mode 100644 index 00000000000..c7fd19fdca3 --- /dev/null +++ b/src/test/regress/expected/incremental_matview.out @@ -0,0 +1,667 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ERROR: materialized view "mv_ivm_1" has not been populated +HINT: Use the REFRESH MATERIALIZED VIEW command. +REFRESH MATERIALIZED VIEW mv_ivm_1; +NOTICE: could not create an index on materialized view "mv_ivm_1" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 17 +(1 row) + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 1 +(1 row) + +ROLLBACK; +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- DISTINCT not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT * FROM mv_base_a; +ERROR: DISTINCT is not supported on incrementally maintainable materialized view +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +NOTICE: could not create an index on materialized view "mv_ivm_func" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +NOTICE: could not create an index on materialized view "mv_ivm_no_tbl" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- result of materialized view have duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_duplicate" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 20 + 30 + 40 + 50 +(6 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +ROLLBACK; +-- aggregate not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +ERROR: aggregate function is not supported on incrementally maintainable materialized view +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +NOTICE: could not create an index on materialized view "mv_self" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +----+---- + 10 | 10 + 20 | 20 + 30 | 30 +(3 rows) + +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 30 | 30 + 40 | 40 + 200 | 200 +(3 rows) + +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 130 | 130 + 300 | 300 +(4 rows) + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 70 | 70 + 70 | 77 + 77 | 70 + 77 | 77 + 130 | 130 + 300 | 300 +(8 rows) + +ROLLBACK; +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY v1; + v1 | v2 +----+----- + 10 | 100 + 20 | 200 + 30 | 300 +(3 rows) + +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv ORDER BY v1; + v1 | v2 +------+----- + 10 | 100 + 11 | 100 + 1020 | 200 + 1020 | 222 +(4 rows) + +ROLLBACK; +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +NOTICE: created index "mv_ri_index" on materialized view "mv_ri" +SELECT * FROM mv_ri ORDER BY i1; + i1 | i2 +----+---- + 1 | 1 + 2 | 2 + 3 | 3 +(3 rows) + +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; + i1 | i2 +----+---- + 3 | 3 + 10 | 10 +(2 rows) + +ROLLBACK; +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | +(2 rows) + +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | 20 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i +--- +(0 rows) + +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; + i +--- + 1 + +(2 rows) + +ROLLBACK; +-- IMMV containing user defined type +BEGIN; +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: return type mytype is only a shell +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: argument type mytype is only a shell +LINE 1: CREATE FUNCTION mytype_out(mytype) + ^ +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +NOTICE: could not create an index on materialized view "mv_mytype" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + x +--- + 1 +(1 row) + +ROLLBACK; +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +ERROR: OUTER JOIN is not supported on incrementally maintainable materialized view +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +ERROR: CTE is not supported on incrementally maintainable materialized view +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +ERROR: ORDER BY clause is not supported on incrementally maintainable materialized view +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; +ERROR: HAVING clause is not supported on incrementally maintainable materialized view +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; +ERROR: mutable function is not supported on incrementally maintainable materialized view +HINT: functions must be marked IMMUTABLE +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; +ERROR: LIMIT/OFFSET clause is not supported on incrementally maintainable materialized view +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; +ERROR: DISTINCT is not supported on incrementally maintainable materialized view +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); +ERROR: TABLESAMPLE clause is not supported on incrementally maintainable materialized view +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; +ERROR: window functions are not supported on incrementally maintainable materialized view +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ERROR: inheritance parent is not supported on incrementally maintainable materialized view +ROLLBACK; +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; +ERROR: UNION/INTERSECT/EXCEPT statements are not supported on incrementally maintainable materialized view +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; +ERROR: empty target list is not supported on incrementally maintainable materialized view +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; +ERROR: FOR UPDATE/SHARE clause is not supported on incrementally maintainable materialized view +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; +ERROR: column name __ivm_count__ is not supported on incrementally maintainable materialized view +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; +ERROR: aggregate function is not supported on incrementally maintainable materialized view +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); +ERROR: VALUES is not supported on incrementally maintainable materialized view +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +NOTICE: role "regress_ivm_admin" does not exist, skipping +DROP USER IF EXISTS regress_ivm_user; +NOTICE: role "regress_ivm_user" does not exist, skipping +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +NOTICE: could not create an index on materialized view "ivm_rls" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user +(1 row) + +RESET SESSION AUTHORIZATION; +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user + 3 | baz | regress_ivm_user +(2 rows) + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +-- +(1 row) + +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+-------+------------------ + 2 | bar | regress_ivm_user + 3 | baz | regress_ivm_user + 6 | corge | regress_ivm_user +(3 rows) + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +NOTICE: could not create an index on materialized view "ivm_rls2" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +RESET SESSION AUTHORIZATION; +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +-- +(1 row) + +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + id | data | owner | num +----+-------+------------------+--------- + 2 | bar | regress_ivm_user | two + 3 | baz_2 | regress_ivm_user | three_2 + 6 | corge | regress_ivm_user | six +(3 rows) + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +NOTICE: could not create an index on materialized view "mv_update_same" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + i +--- + 2 +(1 row) + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +NOTICE: created index "mv_self_ref_index" on materialized view "mv_self_ref" +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; + a | b +----+---- + 11 | + 12 | 11 + 13 | 12 +(3 rows) + +ROLLBACK; +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; +NOTICE: created index "mv_idx3_index" on materialized view "mv_idx3" +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +NOTICE: could not create an index on materialized view "mv_idx4" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; +NOTICE: could not create an index on materialized view "mv_idx5" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); +NOTICE: could not create an index on materialized view "mv_idx6" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ERROR: data type json has no default operator class for access method "btree" +ROLLBACK; +-- cleanup +DROP TABLE rls_tbl CASCADE; +NOTICE: drop cascades to 2 other objects +DETAIL: drop cascades to materialized view ivm_rls +drop cascades to materialized view ivm_rls2 +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; +DROP TABLE mv_base_b CASCADE; +NOTICE: drop cascades to 3 other objects +DETAIL: drop cascades to materialized view mv_ivm_1 +drop cascades to view b_view +drop cascades to materialized view b_mview +DROP TABLE mv_base_a CASCADE; diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index 8fa0a6c47fb..7caca5f64fd 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -77,6 +77,7 @@ test: brin_bloom brin_multi # Another group of parallel tests # ---------- test: create_table_like alter_generic alter_operator misc async dbsize merge misc_functions nls sysviews tsrf tid tidscan tidrangescan collate.utf8 collate.icu.utf8 incremental_sort create_role without_overlaps generated_virtual +test: incremental_matview # collate.linux.utf8 and collate.icu.utf8 tests cannot be run in parallel with each other # psql depends on create_am diff --git a/src/test/regress/sql/incremental_matview.sql b/src/test/regress/sql/incremental_matview.sql new file mode 100644 index 00000000000..7313ad82f3e --- /dev/null +++ b/src/test/regress/sql/incremental_matview.sql @@ -0,0 +1,407 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); + +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +REFRESH MATERIALIZED VIEW mv_ivm_1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; + +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; +ROLLBACK; + +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- DISTINCT not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT * FROM mv_base_a; + +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; + + +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +ROLLBACK; + +-- result of materialized view have duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +ROLLBACK; + +-- aggregate not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; + +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +SELECT * FROM mv_self ORDER BY v1; +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; +SELECT * FROM mv_self ORDER BY v1; + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + +ROLLBACK; + +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +SELECT * FROM mv ORDER BY v1; +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; +SELECT * FROM mv ORDER BY v1; +ROLLBACK; + +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +SELECT * FROM mv_ri ORDER BY i1; +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; +ROLLBACK; + +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +-- IMMV containing user defined type +BEGIN; + +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); + +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; + +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); + +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); + +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + +ROLLBACK; + +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; + +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; + +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; + +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; + +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; + +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); + +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; + +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ROLLBACK; + +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; + +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; + +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; + +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; + +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; + +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); + +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +DROP USER IF EXISTS regress_ivm_user; +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; + +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); + +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; + +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; + +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; +RESET SESSION AUTHORIZATION; + +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +RESET SESSION AUTHORIZATION; + +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; +ROLLBACK; + +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); + +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; + +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; + +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); + +ROLLBACK; + +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ROLLBACK; + +-- cleanup + +DROP TABLE rls_tbl CASCADE; +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; + +DROP TABLE mv_base_b CASCADE; +DROP TABLE mv_base_a CASCADE; -- 2.43.0 --Multipart=_Fri__3_Jul_2026_19_11_16_+0900_CskxSIu_iGcDMEyM Content-Type: text/x-diff; name="v39-0006-Add-Incremental-View-Maintenance-support.patch" Content-Disposition: attachment; filename="v39-0006-Add-Incremental-View-Maintenance-support.patch" Content-Transfer-Encoding: 7bit ^ permalink raw reply [nested|flat] 78+ messages in thread
* [PATCH v39 7/8] Add regression tests for Incremental View Maintenance @ 2026-05-29 09:31 Yugo Nagata <[email protected]> 0 siblings, 0 replies; 78+ messages in thread From: Yugo Nagata @ 2026-05-29 09:31 UTC (permalink / raw) --- .../isolation/expected/ivm-create-insert.out | 285 ++++++++ .../isolation/expected/ivm-create-insert2.out | 305 ++++++++ .../isolation/expected/ivm-create-insert3.out | 305 ++++++++ .../isolation/expected/ivm-insert-insert.out | 497 +++++++++++++ .../isolation/expected/ivm-insert-insert2.out | 373 ++++++++++ .../isolation/expected/ivm-insert-insert3.out | 373 ++++++++++ .../isolation/expected/ivm-refresh-insert.out | 213 ++++++ .../expected/ivm-refresh-insert2.out | 191 +++++ .../expected/ivm-refresh-insert3.out | 191 +++++ src/test/isolation/isolation_schedule | 9 + .../isolation/specs/ivm-create-insert.spec | 47 ++ .../isolation/specs/ivm-create-insert2.spec | 54 ++ .../isolation/specs/ivm-create-insert3.spec | 54 ++ .../isolation/specs/ivm-insert-insert.spec | 62 ++ .../isolation/specs/ivm-insert-insert2.spec | 62 ++ .../isolation/specs/ivm-insert-insert3.spec | 62 ++ .../isolation/specs/ivm-refresh-insert.spec | 46 ++ .../isolation/specs/ivm-refresh-insert2.spec | 46 ++ .../isolation/specs/ivm-refresh-insert3.spec | 46 ++ .../regress/expected/incremental_matview.out | 667 ++++++++++++++++++ src/test/regress/parallel_schedule | 1 + src/test/regress/sql/incremental_matview.sql | 407 +++++++++++ 22 files changed, 4296 insertions(+) create mode 100644 src/test/isolation/expected/ivm-create-insert.out create mode 100644 src/test/isolation/expected/ivm-create-insert2.out create mode 100644 src/test/isolation/expected/ivm-create-insert3.out create mode 100644 src/test/isolation/expected/ivm-insert-insert.out create mode 100644 src/test/isolation/expected/ivm-insert-insert2.out create mode 100644 src/test/isolation/expected/ivm-insert-insert3.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert2.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert3.out create mode 100644 src/test/isolation/specs/ivm-create-insert.spec create mode 100644 src/test/isolation/specs/ivm-create-insert2.spec create mode 100644 src/test/isolation/specs/ivm-create-insert3.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert2.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert3.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert2.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert3.spec create mode 100644 src/test/regress/expected/incremental_matview.out create mode 100644 src/test/regress/sql/incremental_matview.sql diff --git a/src/test/isolation/expected/ivm-create-insert.out b/src/test/isolation/expected/ivm-create-insert.out new file mode 100644 index 00000000000..5da00043aba --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert.out @@ -0,0 +1,285 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-create-insert2.out b/src/test/isolation/expected/ivm-create-insert2.out new file mode 100644 index 00000000000..907d892c6d4 --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert2.out @@ -0,0 +1,305 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + diff --git a/src/test/isolation/expected/ivm-create-insert3.out b/src/test/isolation/expected/ivm-create-insert3.out new file mode 100644 index 00000000000..907d892c6d4 --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert3.out @@ -0,0 +1,305 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert.out b/src/test/isolation/expected/ivm-insert-insert.out new file mode 100644 index 00000000000..5ca4cfea677 --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert.out @@ -0,0 +1,497 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; <waiting ...> +step c1: COMMIT; +step update2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; <waiting ...> +step c1: COMMIT; +step update2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; <waiting ...> +step c2: COMMIT; +step update1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; <waiting ...> +step c2: COMMIT; +step update1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); <waiting ...> +step c1: COMMIT; +step insert2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); <waiting ...> +step c1: COMMIT; +step insert2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); <waiting ...> +step c2: COMMIT; +step insert1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); <waiting ...> +step c2: COMMIT; +step insert1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert2.out b/src/test/isolation/expected/ivm-insert-insert2.out new file mode 100644 index 00000000000..e1c66d4de5e --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert2.out @@ -0,0 +1,373 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert3.out b/src/test/isolation/expected/ivm-insert-insert3.out new file mode 100644 index 00000000000..e1c66d4de5e --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert3.out @@ -0,0 +1,373 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert.out b/src/test/isolation/expected/ivm-refresh-insert.out new file mode 100644 index 00000000000..a925938bf1c --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert.out @@ -0,0 +1,213 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert2.out b/src/test/isolation/expected/ivm-refresh-insert2.out new file mode 100644 index 00000000000..dc1b16ae34e --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert2.out @@ -0,0 +1,191 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert3.out b/src/test/isolation/expected/ivm-refresh-insert3.out new file mode 100644 index 00000000000..dc1b16ae34e --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert3.out @@ -0,0 +1,191 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/isolation_schedule b/src/test/isolation/isolation_schedule index b8ebe92553c..6b7e873b370 100644 --- a/src/test/isolation/isolation_schedule +++ b/src/test/isolation/isolation_schedule @@ -128,3 +128,12 @@ test: matview-write-skew test: lock-nowait test: for-portion-of test: ddl-dependency-locking +test: ivm-create-insert +test: ivm-create-insert2 +test: ivm-create-insert3 +test: ivm-insert-insert +test: ivm-insert-insert2 +test: ivm-insert-insert3 +test: ivm-refresh-insert +test: ivm-refresh-insert2 +test: ivm-refresh-insert3 diff --git a/src/test/isolation/specs/ivm-create-insert.spec b/src/test/isolation/specs/ivm-create-insert.spec new file mode 100644 index 00000000000..ccd6fd080a9 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert.spec @@ -0,0 +1,47 @@ +# Test interaction between concurrent transactions performing +# create and insert in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-create-insert2.spec b/src/test/isolation/specs/ivm-create-insert2.spec new file mode 100644 index 00000000000..02cec85ae07 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert2.spec @@ -0,0 +1,54 @@ +# Test interaction between concurrent transactions performing +# create and insert in REPEATABLE READ isolation level +# +# Note: +# In this isolation level, it is possible that create_immv could +# create an inconsistent view not including effects of a concurrent +# transaction. So, an warning message is raised to suggest using it +# in READ COMMITTED or executing refresh_immv to make sure to +# make the view contents consistent. + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-create-insert3.spec b/src/test/isolation/specs/ivm-create-insert3.spec new file mode 100644 index 00000000000..19ce03185a4 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert3.spec @@ -0,0 +1,54 @@ +# Test interaction between concurrent transactions performing +# create and insert in SERIALIZABLE isolation level +# +# Note: +# In this isolation level, it is possible that create_immv could +# create an inconsistent view not including effects of a concurrent +# transaction. So, an warning message is raised to suggest using it +# in READ COMMITTED or executing refresh_immv to make sure to +# make the view contents consistent. + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert.spec b/src/test/isolation/specs/ivm-insert-insert.spec new file mode 100644 index 00000000000..b8f794ca191 --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert2.spec b/src/test/isolation/specs/ivm-insert-insert2.spec new file mode 100644 index 00000000000..ed086d1ba1e --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert2.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in REPEATABLE READ isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert3.spec b/src/test/isolation/specs/ivm-insert-insert3.spec new file mode 100644 index 00000000000..b18bd121033 --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert3.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in SERIALIZABLE isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert.spec b/src/test/isolation/specs/ivm-refresh-insert.spec new file mode 100644 index 00000000000..d7181251962 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert2.spec b/src/test/isolation/specs/ivm-refresh-insert2.spec new file mode 100644 index 00000000000..f2d1d5013f2 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert2.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in REPEATABLE READ isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert3.spec b/src/test/isolation/specs/ivm-refresh-insert3.spec new file mode 100644 index 00000000000..0ec2b1d1de0 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert3.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in SERIALIZABLE isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/regress/expected/incremental_matview.out b/src/test/regress/expected/incremental_matview.out new file mode 100644 index 00000000000..c7fd19fdca3 --- /dev/null +++ b/src/test/regress/expected/incremental_matview.out @@ -0,0 +1,667 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ERROR: materialized view "mv_ivm_1" has not been populated +HINT: Use the REFRESH MATERIALIZED VIEW command. +REFRESH MATERIALIZED VIEW mv_ivm_1; +NOTICE: could not create an index on materialized view "mv_ivm_1" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 17 +(1 row) + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 1 +(1 row) + +ROLLBACK; +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- DISTINCT not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT * FROM mv_base_a; +ERROR: DISTINCT is not supported on incrementally maintainable materialized view +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +NOTICE: could not create an index on materialized view "mv_ivm_func" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +NOTICE: could not create an index on materialized view "mv_ivm_no_tbl" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- result of materialized view have duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_duplicate" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 20 + 30 + 40 + 50 +(6 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +ROLLBACK; +-- aggregate not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +ERROR: aggregate function is not supported on incrementally maintainable materialized view +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +NOTICE: could not create an index on materialized view "mv_self" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +----+---- + 10 | 10 + 20 | 20 + 30 | 30 +(3 rows) + +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 30 | 30 + 40 | 40 + 200 | 200 +(3 rows) + +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 130 | 130 + 300 | 300 +(4 rows) + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 70 | 70 + 70 | 77 + 77 | 70 + 77 | 77 + 130 | 130 + 300 | 300 +(8 rows) + +ROLLBACK; +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY v1; + v1 | v2 +----+----- + 10 | 100 + 20 | 200 + 30 | 300 +(3 rows) + +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv ORDER BY v1; + v1 | v2 +------+----- + 10 | 100 + 11 | 100 + 1020 | 200 + 1020 | 222 +(4 rows) + +ROLLBACK; +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +NOTICE: created index "mv_ri_index" on materialized view "mv_ri" +SELECT * FROM mv_ri ORDER BY i1; + i1 | i2 +----+---- + 1 | 1 + 2 | 2 + 3 | 3 +(3 rows) + +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; + i1 | i2 +----+---- + 3 | 3 + 10 | 10 +(2 rows) + +ROLLBACK; +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | +(2 rows) + +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | 20 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i +--- +(0 rows) + +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; + i +--- + 1 + +(2 rows) + +ROLLBACK; +-- IMMV containing user defined type +BEGIN; +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: return type mytype is only a shell +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: argument type mytype is only a shell +LINE 1: CREATE FUNCTION mytype_out(mytype) + ^ +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +NOTICE: could not create an index on materialized view "mv_mytype" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + x +--- + 1 +(1 row) + +ROLLBACK; +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +ERROR: OUTER JOIN is not supported on incrementally maintainable materialized view +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +ERROR: CTE is not supported on incrementally maintainable materialized view +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +ERROR: ORDER BY clause is not supported on incrementally maintainable materialized view +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; +ERROR: HAVING clause is not supported on incrementally maintainable materialized view +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; +ERROR: mutable function is not supported on incrementally maintainable materialized view +HINT: functions must be marked IMMUTABLE +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; +ERROR: LIMIT/OFFSET clause is not supported on incrementally maintainable materialized view +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; +ERROR: DISTINCT is not supported on incrementally maintainable materialized view +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); +ERROR: TABLESAMPLE clause is not supported on incrementally maintainable materialized view +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; +ERROR: window functions are not supported on incrementally maintainable materialized view +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ERROR: inheritance parent is not supported on incrementally maintainable materialized view +ROLLBACK; +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; +ERROR: UNION/INTERSECT/EXCEPT statements are not supported on incrementally maintainable materialized view +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; +ERROR: empty target list is not supported on incrementally maintainable materialized view +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; +ERROR: FOR UPDATE/SHARE clause is not supported on incrementally maintainable materialized view +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; +ERROR: column name __ivm_count__ is not supported on incrementally maintainable materialized view +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; +ERROR: aggregate function is not supported on incrementally maintainable materialized view +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); +ERROR: VALUES is not supported on incrementally maintainable materialized view +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +NOTICE: role "regress_ivm_admin" does not exist, skipping +DROP USER IF EXISTS regress_ivm_user; +NOTICE: role "regress_ivm_user" does not exist, skipping +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +NOTICE: could not create an index on materialized view "ivm_rls" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user +(1 row) + +RESET SESSION AUTHORIZATION; +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user + 3 | baz | regress_ivm_user +(2 rows) + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +-- +(1 row) + +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+-------+------------------ + 2 | bar | regress_ivm_user + 3 | baz | regress_ivm_user + 6 | corge | regress_ivm_user +(3 rows) + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +NOTICE: could not create an index on materialized view "ivm_rls2" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +RESET SESSION AUTHORIZATION; +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +-- +(1 row) + +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + id | data | owner | num +----+-------+------------------+--------- + 2 | bar | regress_ivm_user | two + 3 | baz_2 | regress_ivm_user | three_2 + 6 | corge | regress_ivm_user | six +(3 rows) + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +NOTICE: could not create an index on materialized view "mv_update_same" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + i +--- + 2 +(1 row) + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +NOTICE: created index "mv_self_ref_index" on materialized view "mv_self_ref" +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; + a | b +----+---- + 11 | + 12 | 11 + 13 | 12 +(3 rows) + +ROLLBACK; +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; +NOTICE: created index "mv_idx3_index" on materialized view "mv_idx3" +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +NOTICE: could not create an index on materialized view "mv_idx4" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; +NOTICE: could not create an index on materialized view "mv_idx5" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); +NOTICE: could not create an index on materialized view "mv_idx6" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ERROR: data type json has no default operator class for access method "btree" +ROLLBACK; +-- cleanup +DROP TABLE rls_tbl CASCADE; +NOTICE: drop cascades to 2 other objects +DETAIL: drop cascades to materialized view ivm_rls +drop cascades to materialized view ivm_rls2 +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; +DROP TABLE mv_base_b CASCADE; +NOTICE: drop cascades to 3 other objects +DETAIL: drop cascades to materialized view mv_ivm_1 +drop cascades to view b_view +drop cascades to materialized view b_mview +DROP TABLE mv_base_a CASCADE; diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index 8fa0a6c47fb..7caca5f64fd 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -77,6 +77,7 @@ test: brin_bloom brin_multi # Another group of parallel tests # ---------- test: create_table_like alter_generic alter_operator misc async dbsize merge misc_functions nls sysviews tsrf tid tidscan tidrangescan collate.utf8 collate.icu.utf8 incremental_sort create_role without_overlaps generated_virtual +test: incremental_matview # collate.linux.utf8 and collate.icu.utf8 tests cannot be run in parallel with each other # psql depends on create_am diff --git a/src/test/regress/sql/incremental_matview.sql b/src/test/regress/sql/incremental_matview.sql new file mode 100644 index 00000000000..7313ad82f3e --- /dev/null +++ b/src/test/regress/sql/incremental_matview.sql @@ -0,0 +1,407 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); + +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +REFRESH MATERIALIZED VIEW mv_ivm_1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; + +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; +ROLLBACK; + +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- DISTINCT not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT * FROM mv_base_a; + +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; + + +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +ROLLBACK; + +-- result of materialized view have duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +ROLLBACK; + +-- aggregate not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; + +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +SELECT * FROM mv_self ORDER BY v1; +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; +SELECT * FROM mv_self ORDER BY v1; + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + +ROLLBACK; + +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +SELECT * FROM mv ORDER BY v1; +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; +SELECT * FROM mv ORDER BY v1; +ROLLBACK; + +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +SELECT * FROM mv_ri ORDER BY i1; +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; +ROLLBACK; + +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +-- IMMV containing user defined type +BEGIN; + +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); + +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; + +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); + +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); + +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + +ROLLBACK; + +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; + +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; + +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; + +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; + +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; + +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); + +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; + +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ROLLBACK; + +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; + +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; + +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; + +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; + +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; + +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); + +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +DROP USER IF EXISTS regress_ivm_user; +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; + +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); + +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; + +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; + +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; +RESET SESSION AUTHORIZATION; + +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +RESET SESSION AUTHORIZATION; + +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; +ROLLBACK; + +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); + +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; + +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; + +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); + +ROLLBACK; + +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ROLLBACK; + +-- cleanup + +DROP TABLE rls_tbl CASCADE; +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; + +DROP TABLE mv_base_b CASCADE; +DROP TABLE mv_base_a CASCADE; -- 2.43.0 --Multipart=_Fri__3_Jul_2026_19_11_16_+0900_CskxSIu_iGcDMEyM Content-Type: text/x-diff; name="v39-0006-Add-Incremental-View-Maintenance-support.patch" Content-Disposition: attachment; filename="v39-0006-Add-Incremental-View-Maintenance-support.patch" Content-Transfer-Encoding: 7bit ^ permalink raw reply [nested|flat] 78+ messages in thread
* [PATCH v38 10/11] Add regression tests for Incremental View Maintenance @ 2026-05-29 09:31 Yugo Nagata <[email protected]> 0 siblings, 0 replies; 78+ messages in thread From: Yugo Nagata @ 2026-05-29 09:31 UTC (permalink / raw) --- .../isolation/expected/ivm-create-insert.out | 285 +++++ .../isolation/expected/ivm-create-insert2.out | 305 +++++ .../isolation/expected/ivm-create-insert3.out | 305 +++++ .../isolation/expected/ivm-insert-insert.out | 497 ++++++++ .../isolation/expected/ivm-insert-insert2.out | 373 ++++++ .../isolation/expected/ivm-insert-insert3.out | 373 ++++++ .../isolation/expected/ivm-refresh-insert.out | 213 ++++ .../expected/ivm-refresh-insert2.out | 191 +++ .../expected/ivm-refresh-insert3.out | 191 +++ src/test/isolation/isolation_schedule | 9 + .../isolation/specs/ivm-create-insert.spec | 47 + .../isolation/specs/ivm-create-insert2.spec | 54 + .../isolation/specs/ivm-create-insert3.spec | 54 + .../isolation/specs/ivm-insert-insert.spec | 62 + .../isolation/specs/ivm-insert-insert2.spec | 62 + .../isolation/specs/ivm-insert-insert3.spec | 62 + .../isolation/specs/ivm-refresh-insert.spec | 46 + .../isolation/specs/ivm-refresh-insert2.spec | 46 + .../isolation/specs/ivm-refresh-insert3.spec | 46 + .../regress/expected/incremental_matview.out | 1100 +++++++++++++++++ src/test/regress/parallel_schedule | 1 + src/test/regress/sql/incremental_matview.sql | 580 +++++++++ 22 files changed, 4902 insertions(+) create mode 100644 src/test/isolation/expected/ivm-create-insert.out create mode 100644 src/test/isolation/expected/ivm-create-insert2.out create mode 100644 src/test/isolation/expected/ivm-create-insert3.out create mode 100644 src/test/isolation/expected/ivm-insert-insert.out create mode 100644 src/test/isolation/expected/ivm-insert-insert2.out create mode 100644 src/test/isolation/expected/ivm-insert-insert3.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert2.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert3.out create mode 100644 src/test/isolation/specs/ivm-create-insert.spec create mode 100644 src/test/isolation/specs/ivm-create-insert2.spec create mode 100644 src/test/isolation/specs/ivm-create-insert3.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert2.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert3.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert2.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert3.spec create mode 100644 src/test/regress/expected/incremental_matview.out create mode 100644 src/test/regress/sql/incremental_matview.sql diff --git a/src/test/isolation/expected/ivm-create-insert.out b/src/test/isolation/expected/ivm-create-insert.out new file mode 100644 index 00000000000..5da00043aba --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert.out @@ -0,0 +1,285 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-create-insert2.out b/src/test/isolation/expected/ivm-create-insert2.out new file mode 100644 index 00000000000..907d892c6d4 --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert2.out @@ -0,0 +1,305 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + diff --git a/src/test/isolation/expected/ivm-create-insert3.out b/src/test/isolation/expected/ivm-create-insert3.out new file mode 100644 index 00000000000..907d892c6d4 --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert3.out @@ -0,0 +1,305 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert.out b/src/test/isolation/expected/ivm-insert-insert.out new file mode 100644 index 00000000000..5ca4cfea677 --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert.out @@ -0,0 +1,497 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; <waiting ...> +step c1: COMMIT; +step update2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; <waiting ...> +step c1: COMMIT; +step update2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; <waiting ...> +step c2: COMMIT; +step update1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; <waiting ...> +step c2: COMMIT; +step update1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); <waiting ...> +step c1: COMMIT; +step insert2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); <waiting ...> +step c1: COMMIT; +step insert2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); <waiting ...> +step c2: COMMIT; +step insert1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); <waiting ...> +step c2: COMMIT; +step insert1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert2.out b/src/test/isolation/expected/ivm-insert-insert2.out new file mode 100644 index 00000000000..e1c66d4de5e --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert2.out @@ -0,0 +1,373 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert3.out b/src/test/isolation/expected/ivm-insert-insert3.out new file mode 100644 index 00000000000..e1c66d4de5e --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert3.out @@ -0,0 +1,373 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert.out b/src/test/isolation/expected/ivm-refresh-insert.out new file mode 100644 index 00000000000..a925938bf1c --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert.out @@ -0,0 +1,213 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert2.out b/src/test/isolation/expected/ivm-refresh-insert2.out new file mode 100644 index 00000000000..dc1b16ae34e --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert2.out @@ -0,0 +1,191 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert3.out b/src/test/isolation/expected/ivm-refresh-insert3.out new file mode 100644 index 00000000000..dc1b16ae34e --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert3.out @@ -0,0 +1,191 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/isolation_schedule b/src/test/isolation/isolation_schedule index b8ebe92553c..6b7e873b370 100644 --- a/src/test/isolation/isolation_schedule +++ b/src/test/isolation/isolation_schedule @@ -128,3 +128,12 @@ test: matview-write-skew test: lock-nowait test: for-portion-of test: ddl-dependency-locking +test: ivm-create-insert +test: ivm-create-insert2 +test: ivm-create-insert3 +test: ivm-insert-insert +test: ivm-insert-insert2 +test: ivm-insert-insert3 +test: ivm-refresh-insert +test: ivm-refresh-insert2 +test: ivm-refresh-insert3 diff --git a/src/test/isolation/specs/ivm-create-insert.spec b/src/test/isolation/specs/ivm-create-insert.spec new file mode 100644 index 00000000000..ccd6fd080a9 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert.spec @@ -0,0 +1,47 @@ +# Test interaction between concurrent transactions performing +# create and insert in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-create-insert2.spec b/src/test/isolation/specs/ivm-create-insert2.spec new file mode 100644 index 00000000000..02cec85ae07 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert2.spec @@ -0,0 +1,54 @@ +# Test interaction between concurrent transactions performing +# create and insert in REPEATABLE READ isolation level +# +# Note: +# In this isolation level, it is possible that create_immv could +# create an inconsistent view not including effects of a concurrent +# transaction. So, an warning message is raised to suggest using it +# in READ COMMITTED or executing refresh_immv to make sure to +# make the view contents consistent. + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-create-insert3.spec b/src/test/isolation/specs/ivm-create-insert3.spec new file mode 100644 index 00000000000..19ce03185a4 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert3.spec @@ -0,0 +1,54 @@ +# Test interaction between concurrent transactions performing +# create and insert in SERIALIZABLE isolation level +# +# Note: +# In this isolation level, it is possible that create_immv could +# create an inconsistent view not including effects of a concurrent +# transaction. So, an warning message is raised to suggest using it +# in READ COMMITTED or executing refresh_immv to make sure to +# make the view contents consistent. + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert.spec b/src/test/isolation/specs/ivm-insert-insert.spec new file mode 100644 index 00000000000..b8f794ca191 --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert2.spec b/src/test/isolation/specs/ivm-insert-insert2.spec new file mode 100644 index 00000000000..ed086d1ba1e --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert2.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in REPEATABLE READ isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert3.spec b/src/test/isolation/specs/ivm-insert-insert3.spec new file mode 100644 index 00000000000..b18bd121033 --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert3.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in SERIALIZABLE isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert.spec b/src/test/isolation/specs/ivm-refresh-insert.spec new file mode 100644 index 00000000000..d7181251962 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert2.spec b/src/test/isolation/specs/ivm-refresh-insert2.spec new file mode 100644 index 00000000000..f2d1d5013f2 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert2.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in REPEATABLE READ isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert3.spec b/src/test/isolation/specs/ivm-refresh-insert3.spec new file mode 100644 index 00000000000..0ec2b1d1de0 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert3.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in SERIALIZABLE isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/regress/expected/incremental_matview.out b/src/test/regress/expected/incremental_matview.out new file mode 100644 index 00000000000..f215aa88e48 --- /dev/null +++ b/src/test/regress/expected/incremental_matview.out @@ -0,0 +1,1100 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ERROR: materialized view "mv_ivm_1" has not been populated +HINT: Use the REFRESH MATERIALIZED VIEW command. +REFRESH MATERIALIZED VIEW mv_ivm_1; +NOTICE: could not create an index on materialized view "mv_ivm_1" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 17 +(1 row) + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 1 +(1 row) + +ROLLBACK; +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_rename_index" on materialized view "mv_ivm_rename" +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +ERROR: IVM column can not be renamed +DROP MATERIALIZED VIEW mv_ivm_rename; +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_unique_index" on materialized view "mv_ivm_unique" +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +ERROR: unique index creation on IVM columns is not supported +DROP MATERIALIZED VIEW mv_ivm_unique; +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +NOTICE: could not create an index on materialized view "mv_ivm_func" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +NOTICE: could not create an index on materialized view "mv_ivm_no_tbl" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_duplicate" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +NOTICE: created index "mv_ivm_distinct_index" on materialized view "mv_ivm_distinct" +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 20 + 30 + 40 + 50 +(6 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +ROLLBACK; +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 120 | 2 | 60.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+---------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 220 | 2 | 110.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 20 | 1 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 120 | 2 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; + sum | count +-----+------- +(0 rows) + +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; + i | sum | count +---+-----+------- +(0 rows) + +ROLLBACK; +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 150 | 5 | 30.0000000000000000 +(1 row) + +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 210 | 6 | 35.0000000000000000 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +NOTICE: created index "mv_ivm_avg_bug_index" on materialized view "mv_ivm_avg_bug" +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 3 | 3.3333333333333333 + 2 | 80 | 3 | 26.6666666666666667 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_min_max_index" on materialized view "mv_ivm_min_max" +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 10 + 2 | 20 | 20 + 3 | 30 | 30 + 4 | 40 | 40 + 5 | 50 | 50 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 12 + 2 | 20 | 22 + 3 | 30 | 32 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 11 | 12 + 2 | 20 | 22 + 3 | 30 | 31 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min_max" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 50 +(1 row) + +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 0 | 70 +(1 row) + +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 60 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + | +(1 row) + +ROLLBACK; +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min; + min +----- + 10 +(1 row) + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + min +----- + 20 +(1 row) + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; + min +----- + 30 +(1 row) + +ROLLBACK; +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | sum +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | b +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ERROR: too many column names were specified +ROLLBACK; +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +NOTICE: could not create an index on materialized view "mv_self" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +----+---- + 10 | 10 + 20 | 20 + 30 | 30 +(3 rows) + +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 30 | 30 + 40 | 40 + 200 | 200 +(3 rows) + +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 130 | 130 + 300 | 300 +(4 rows) + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 70 | 70 + 70 | 77 + 77 | 70 + 77 | 77 + 130 | 130 + 300 | 300 +(8 rows) + +ROLLBACK; +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY v1; + v1 | v2 +----+----- + 10 | 100 + 20 | 200 + 30 | 300 +(3 rows) + +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv ORDER BY v1; + v1 | v2 +------+----- + 10 | 100 + 11 | 100 + 1020 | 200 + 1020 | 222 +(4 rows) + +ROLLBACK; +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +NOTICE: created index "mv_ri_index" on materialized view "mv_ri" +SELECT * FROM mv_ri ORDER BY i1; + i1 | i2 +----+---- + 1 | 1 + 2 | 2 + 3 | 3 +(3 rows) + +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; + i1 | i2 +----+---- + 3 | 3 + 10 | 10 +(2 rows) + +ROLLBACK; +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | +(2 rows) + +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | 20 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i +--- +(0 rows) + +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; + i +--- + 1 + +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 30 + | 3 +(2 rows) + +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 300 + | 30 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 1 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 4 +(1 row) + +ROLLBACK; +-- IMMV containing user defined type +BEGIN; +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: return type mytype is only a shell +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: argument type mytype is only a shell +LINE 1: CREATE FUNCTION mytype_out(mytype) + ^ +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +NOTICE: could not create an index on materialized view "mv_mytype" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + x +--- + 1 +(1 row) + +ROLLBACK; +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +ERROR: OUTER JOIN is not supported on incrementally maintainable materialized view +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +ERROR: CTE is not supported on incrementally maintainable materialized view +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +ERROR: ORDER BY clause is not supported on incrementally maintainable materialized view +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; +ERROR: HAVING clause is not supported on incrementally maintainable materialized view +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; +ERROR: mutable function is not supported on incrementally maintainable materialized view +HINT: functions must be marked IMMUTABLE +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; +ERROR: LIMIT/OFFSET clause is not supported on incrementally maintainable materialized view +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; +ERROR: DISTINCT ON is not supported on incrementally maintainable materialized view +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); +ERROR: TABLESAMPLE clause is not supported on incrementally maintainable materialized view +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; +ERROR: window functions are not supported on incrementally maintainable materialized view +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +ERROR: aggregate function with FILTER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +ERROR: aggregate function with DISTINCT arguments is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +ERROR: aggregate function with ORDER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); +ERROR: GROUPING SETS, ROLLUP, or CUBE clauses is not supported on incrementally maintainable materialized view +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ERROR: inheritance parent is not supported on incrementally maintainable materialized view +ROLLBACK; +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; +ERROR: UNION/INTERSECT/EXCEPT statements are not supported on incrementally maintainable materialized view +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; +ERROR: empty target list is not supported on incrementally maintainable materialized view +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; +ERROR: FOR UPDATE/SHARE clause is not supported on incrementally maintainable materialized view +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; +ERROR: column name __ivm_count__ is not supported on incrementally maintainable materialized view +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; +ERROR: GROUP BY expression not appearing in select list is not supported on incrementally maintainable materialized view +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); +ERROR: VALUES is not supported on incrementally maintainable materialized view +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +NOTICE: role "regress_ivm_admin" does not exist, skipping +DROP USER IF EXISTS regress_ivm_user; +NOTICE: role "regress_ivm_user" does not exist, skipping +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +NOTICE: could not create an index on materialized view "ivm_rls" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user +(1 row) + +RESET SESSION AUTHORIZATION; +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user + 3 | baz | regress_ivm_user +(2 rows) + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +-- +(1 row) + +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+-------+------------------ + 2 | bar | regress_ivm_user + 3 | baz | regress_ivm_user + 6 | corge | regress_ivm_user +(3 rows) + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +NOTICE: could not create an index on materialized view "ivm_rls2" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +RESET SESSION AUTHORIZATION; +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +-- +(1 row) + +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + id | data | owner | num +----+-------+------------------+--------- + 2 | bar | regress_ivm_user | two + 3 | baz_2 | regress_ivm_user | three_2 + 6 | corge | regress_ivm_user | six +(3 rows) + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +NOTICE: could not create an index on materialized view "mv_update_same" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + i +--- + 2 +(1 row) + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +NOTICE: created index "mv_self_ref_index" on materialized view "mv_self_ref" +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; + a | b +----+---- + 11 | + 12 | 11 + 13 | 12 +(3 rows) + +ROLLBACK; +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; +NOTICE: created index "mv_idx1_index" on materialized view "mv_idx1" +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; +NOTICE: created index "mv_idx2_index" on materialized view "mv_idx2" +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; +NOTICE: created index "mv_idx3_index" on materialized view "mv_idx3" +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +NOTICE: could not create an index on materialized view "mv_idx4" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; +NOTICE: could not create an index on materialized view "mv_idx5" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); +NOTICE: could not create an index on materialized view "mv_idx6" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ERROR: data type json has no default operator class for access method "btree" +ROLLBACK; +-- cleanup +DROP TABLE rls_tbl CASCADE; +NOTICE: drop cascades to 2 other objects +DETAIL: drop cascades to materialized view ivm_rls +drop cascades to materialized view ivm_rls2 +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; +DROP TABLE mv_base_b CASCADE; +NOTICE: drop cascades to 3 other objects +DETAIL: drop cascades to materialized view mv_ivm_1 +drop cascades to view b_view +drop cascades to materialized view b_mview +DROP TABLE mv_base_a CASCADE; diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index 8fa0a6c47fb..7caca5f64fd 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -77,6 +77,7 @@ test: brin_bloom brin_multi # Another group of parallel tests # ---------- test: create_table_like alter_generic alter_operator misc async dbsize merge misc_functions nls sysviews tsrf tid tidscan tidrangescan collate.utf8 collate.icu.utf8 incremental_sort create_role without_overlaps generated_virtual +test: incremental_matview # collate.linux.utf8 and collate.icu.utf8 tests cannot be run in parallel with each other # psql depends on create_am diff --git a/src/test/regress/sql/incremental_matview.sql b/src/test/regress/sql/incremental_matview.sql new file mode 100644 index 00000000000..2d55c393d6f --- /dev/null +++ b/src/test/regress/sql/incremental_matview.sql @@ -0,0 +1,580 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); + +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +REFRESH MATERIALIZED VIEW mv_ivm_1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; + +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; +ROLLBACK; + +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +DROP MATERIALIZED VIEW mv_ivm_rename; + +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +DROP MATERIALIZED VIEW mv_ivm_unique; + +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; + + +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +ROLLBACK; + +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +ROLLBACK; + +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +ROLLBACK; + +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +ROLLBACK; + +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +ROLLBACK; + +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min; + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); + +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; +ROLLBACK; + +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +SELECT * FROM mv_self ORDER BY v1; +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; +SELECT * FROM mv_self ORDER BY v1; + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + +ROLLBACK; + +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +SELECT * FROM mv ORDER BY v1; +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; +SELECT * FROM mv ORDER BY v1; +ROLLBACK; + +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +SELECT * FROM mv_ri ORDER BY i1; +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; +ROLLBACK; + +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +-- IMMV containing user defined type +BEGIN; + +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); + +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; + +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); + +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); + +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + +ROLLBACK; + +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; + +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; + +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; + +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; + +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; + +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); + +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; + +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); + +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ROLLBACK; + +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; + +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; + +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; + +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; + +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; + +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; + +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); + +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +DROP USER IF EXISTS regress_ivm_user; +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; + +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); + +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; + +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; + +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; +RESET SESSION AUTHORIZATION; + +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +RESET SESSION AUTHORIZATION; + +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; +ROLLBACK; + +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); + +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; + +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; + +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; + +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; + +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); + +ROLLBACK; + +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ROLLBACK; + +-- cleanup + +DROP TABLE rls_tbl CASCADE; +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; + +DROP TABLE mv_base_b CASCADE; +DROP TABLE mv_base_a CASCADE; -- 2.43.0 --Multipart=_Wed__1_Jul_2026_00_04_01_+0900_OVSy2WWK_9aByzDJ Content-Type: text/x-diff; name="v38-0009-Add-support-for-min-max-aggregates-for-IVM.patch" Content-Disposition: attachment; filename="v38-0009-Add-support-for-min-max-aggregates-for-IVM.patch" Content-Transfer-Encoding: 7bit ^ permalink raw reply [nested|flat] 78+ messages in thread
* [PATCH v38 10/11] Add regression tests for Incremental View Maintenance @ 2026-05-29 09:31 Yugo Nagata <[email protected]> 0 siblings, 0 replies; 78+ messages in thread From: Yugo Nagata @ 2026-05-29 09:31 UTC (permalink / raw) --- .../isolation/expected/ivm-create-insert.out | 285 +++++ .../isolation/expected/ivm-create-insert2.out | 305 +++++ .../isolation/expected/ivm-create-insert3.out | 305 +++++ .../isolation/expected/ivm-insert-insert.out | 497 ++++++++ .../isolation/expected/ivm-insert-insert2.out | 373 ++++++ .../isolation/expected/ivm-insert-insert3.out | 373 ++++++ .../isolation/expected/ivm-refresh-insert.out | 213 ++++ .../expected/ivm-refresh-insert2.out | 191 +++ .../expected/ivm-refresh-insert3.out | 191 +++ src/test/isolation/isolation_schedule | 9 + .../isolation/specs/ivm-create-insert.spec | 47 + .../isolation/specs/ivm-create-insert2.spec | 54 + .../isolation/specs/ivm-create-insert3.spec | 54 + .../isolation/specs/ivm-insert-insert.spec | 62 + .../isolation/specs/ivm-insert-insert2.spec | 62 + .../isolation/specs/ivm-insert-insert3.spec | 62 + .../isolation/specs/ivm-refresh-insert.spec | 46 + .../isolation/specs/ivm-refresh-insert2.spec | 46 + .../isolation/specs/ivm-refresh-insert3.spec | 46 + .../regress/expected/incremental_matview.out | 1100 +++++++++++++++++ src/test/regress/parallel_schedule | 1 + src/test/regress/sql/incremental_matview.sql | 580 +++++++++ 22 files changed, 4902 insertions(+) create mode 100644 src/test/isolation/expected/ivm-create-insert.out create mode 100644 src/test/isolation/expected/ivm-create-insert2.out create mode 100644 src/test/isolation/expected/ivm-create-insert3.out create mode 100644 src/test/isolation/expected/ivm-insert-insert.out create mode 100644 src/test/isolation/expected/ivm-insert-insert2.out create mode 100644 src/test/isolation/expected/ivm-insert-insert3.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert2.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert3.out create mode 100644 src/test/isolation/specs/ivm-create-insert.spec create mode 100644 src/test/isolation/specs/ivm-create-insert2.spec create mode 100644 src/test/isolation/specs/ivm-create-insert3.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert2.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert3.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert2.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert3.spec create mode 100644 src/test/regress/expected/incremental_matview.out create mode 100644 src/test/regress/sql/incremental_matview.sql diff --git a/src/test/isolation/expected/ivm-create-insert.out b/src/test/isolation/expected/ivm-create-insert.out new file mode 100644 index 00000000000..5da00043aba --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert.out @@ -0,0 +1,285 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-create-insert2.out b/src/test/isolation/expected/ivm-create-insert2.out new file mode 100644 index 00000000000..907d892c6d4 --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert2.out @@ -0,0 +1,305 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + diff --git a/src/test/isolation/expected/ivm-create-insert3.out b/src/test/isolation/expected/ivm-create-insert3.out new file mode 100644 index 00000000000..907d892c6d4 --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert3.out @@ -0,0 +1,305 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert.out b/src/test/isolation/expected/ivm-insert-insert.out new file mode 100644 index 00000000000..5ca4cfea677 --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert.out @@ -0,0 +1,497 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; <waiting ...> +step c1: COMMIT; +step update2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; <waiting ...> +step c1: COMMIT; +step update2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; <waiting ...> +step c2: COMMIT; +step update1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; <waiting ...> +step c2: COMMIT; +step update1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); <waiting ...> +step c1: COMMIT; +step insert2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); <waiting ...> +step c1: COMMIT; +step insert2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); <waiting ...> +step c2: COMMIT; +step insert1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); <waiting ...> +step c2: COMMIT; +step insert1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert2.out b/src/test/isolation/expected/ivm-insert-insert2.out new file mode 100644 index 00000000000..e1c66d4de5e --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert2.out @@ -0,0 +1,373 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert3.out b/src/test/isolation/expected/ivm-insert-insert3.out new file mode 100644 index 00000000000..e1c66d4de5e --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert3.out @@ -0,0 +1,373 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert.out b/src/test/isolation/expected/ivm-refresh-insert.out new file mode 100644 index 00000000000..a925938bf1c --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert.out @@ -0,0 +1,213 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert2.out b/src/test/isolation/expected/ivm-refresh-insert2.out new file mode 100644 index 00000000000..dc1b16ae34e --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert2.out @@ -0,0 +1,191 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert3.out b/src/test/isolation/expected/ivm-refresh-insert3.out new file mode 100644 index 00000000000..dc1b16ae34e --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert3.out @@ -0,0 +1,191 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/isolation_schedule b/src/test/isolation/isolation_schedule index b8ebe92553c..6b7e873b370 100644 --- a/src/test/isolation/isolation_schedule +++ b/src/test/isolation/isolation_schedule @@ -128,3 +128,12 @@ test: matview-write-skew test: lock-nowait test: for-portion-of test: ddl-dependency-locking +test: ivm-create-insert +test: ivm-create-insert2 +test: ivm-create-insert3 +test: ivm-insert-insert +test: ivm-insert-insert2 +test: ivm-insert-insert3 +test: ivm-refresh-insert +test: ivm-refresh-insert2 +test: ivm-refresh-insert3 diff --git a/src/test/isolation/specs/ivm-create-insert.spec b/src/test/isolation/specs/ivm-create-insert.spec new file mode 100644 index 00000000000..ccd6fd080a9 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert.spec @@ -0,0 +1,47 @@ +# Test interaction between concurrent transactions performing +# create and insert in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-create-insert2.spec b/src/test/isolation/specs/ivm-create-insert2.spec new file mode 100644 index 00000000000..02cec85ae07 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert2.spec @@ -0,0 +1,54 @@ +# Test interaction between concurrent transactions performing +# create and insert in REPEATABLE READ isolation level +# +# Note: +# In this isolation level, it is possible that create_immv could +# create an inconsistent view not including effects of a concurrent +# transaction. So, an warning message is raised to suggest using it +# in READ COMMITTED or executing refresh_immv to make sure to +# make the view contents consistent. + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-create-insert3.spec b/src/test/isolation/specs/ivm-create-insert3.spec new file mode 100644 index 00000000000..19ce03185a4 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert3.spec @@ -0,0 +1,54 @@ +# Test interaction between concurrent transactions performing +# create and insert in SERIALIZABLE isolation level +# +# Note: +# In this isolation level, it is possible that create_immv could +# create an inconsistent view not including effects of a concurrent +# transaction. So, an warning message is raised to suggest using it +# in READ COMMITTED or executing refresh_immv to make sure to +# make the view contents consistent. + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert.spec b/src/test/isolation/specs/ivm-insert-insert.spec new file mode 100644 index 00000000000..b8f794ca191 --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert2.spec b/src/test/isolation/specs/ivm-insert-insert2.spec new file mode 100644 index 00000000000..ed086d1ba1e --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert2.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in REPEATABLE READ isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert3.spec b/src/test/isolation/specs/ivm-insert-insert3.spec new file mode 100644 index 00000000000..b18bd121033 --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert3.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in SERIALIZABLE isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert.spec b/src/test/isolation/specs/ivm-refresh-insert.spec new file mode 100644 index 00000000000..d7181251962 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert2.spec b/src/test/isolation/specs/ivm-refresh-insert2.spec new file mode 100644 index 00000000000..f2d1d5013f2 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert2.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in REPEATABLE READ isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert3.spec b/src/test/isolation/specs/ivm-refresh-insert3.spec new file mode 100644 index 00000000000..0ec2b1d1de0 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert3.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in SERIALIZABLE isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/regress/expected/incremental_matview.out b/src/test/regress/expected/incremental_matview.out new file mode 100644 index 00000000000..f215aa88e48 --- /dev/null +++ b/src/test/regress/expected/incremental_matview.out @@ -0,0 +1,1100 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ERROR: materialized view "mv_ivm_1" has not been populated +HINT: Use the REFRESH MATERIALIZED VIEW command. +REFRESH MATERIALIZED VIEW mv_ivm_1; +NOTICE: could not create an index on materialized view "mv_ivm_1" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 17 +(1 row) + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 1 +(1 row) + +ROLLBACK; +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_rename_index" on materialized view "mv_ivm_rename" +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +ERROR: IVM column can not be renamed +DROP MATERIALIZED VIEW mv_ivm_rename; +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +NOTICE: created index "mv_ivm_unique_index" on materialized view "mv_ivm_unique" +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +ERROR: unique index creation on IVM columns is not supported +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +ERROR: unique index creation on IVM columns is not supported +DROP MATERIALIZED VIEW mv_ivm_unique; +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +NOTICE: could not create an index on materialized view "mv_ivm_func" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +NOTICE: could not create an index on materialized view "mv_ivm_no_tbl" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_duplicate" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +NOTICE: created index "mv_ivm_distinct_index" on materialized view "mv_ivm_distinct" +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 20 + 30 + 40 + 50 +(6 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +SELECT * FROM mv_ivm_distinct ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +ROLLBACK; +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 120 | 2 | 60.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+---------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 220 | 2 | 110.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 20 | 1 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; + i | sum | count +---+-----+------- + 1 | 10 | 1 + 2 | 120 | 2 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 +(5 rows) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; + sum | count +-----+------- +(0 rows) + +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; + i | sum | count +---+-----+------- +(0 rows) + +ROLLBACK; +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 150 | 5 | 30.0000000000000000 +(1 row) + +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+--------------------- + 210 | 6 | 35.0000000000000000 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_group" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; + sum | count | avg +-----+-------+----- + | 0 | +(1 row) + +ROLLBACK; +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +NOTICE: created index "mv_ivm_avg_bug_index" on materialized view "mv_ivm_avg_bug" +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 3 | 3.3333333333333333 + 2 | 80 | 3 | 26.6666666666666667 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; + i | sum | count | avg +---+-----+-------+--------------------- + 1 | 10 | 1 | 10.0000000000000000 + 2 | 20 | 1 | 20.0000000000000000 + 3 | 30 | 1 | 30.0000000000000000 + 4 | 40 | 1 | 40.0000000000000000 + 5 | 50 | 1 | 50.0000000000000000 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_min_max_index" on materialized view "mv_ivm_min_max" +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 10 + 2 | 20 | 20 + 3 | 30 | 30 + 4 | 40 | 40 + 5 | 50 | 50 +(5 rows) + +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 10 | 12 + 2 | 20 | 22 + 3 | 30 | 32 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; + i | min | max +---+-----+----- + 1 | 11 | 12 + 2 | 20 | 22 + 3 | 30 | 31 + 4 | 40 | 42 + 5 | 50 | 52 +(5 rows) + +ROLLBACK; +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min_max" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 50 +(1 row) + +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 0 | 70 +(1 row) + +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + 10 | 60 +(1 row) + +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; + min | max +-----+----- + | +(1 row) + +ROLLBACK; +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_min" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_min; + min +----- + 10 +(1 row) + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + min +----- + 20 +(1 row) + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; + min +----- + 30 +(1 row) + +ROLLBACK; +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | sum +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +NOTICE: created index "mv_ivm_agg_index" on materialized view "mv_ivm_agg" +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; + a | b +---+------ + 1 | 110 + 2 | 2200 + 3 | 300 + 4 | 40 + 5 | 50 +(5 rows) + +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ERROR: too many column names were specified +ROLLBACK; +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +NOTICE: could not create an index on materialized view "mv_self" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +----+---- + 10 | 10 + 20 | 20 + 30 | 30 +(3 rows) + +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 30 | 30 + 40 | 40 + 200 | 200 +(3 rows) + +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 130 | 130 + 300 | 300 +(4 rows) + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 70 | 70 + 70 | 77 + 77 | 70 + 77 | 77 + 130 | 130 + 300 | 300 +(8 rows) + +ROLLBACK; +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY v1; + v1 | v2 +----+----- + 10 | 100 + 20 | 200 + 30 | 300 +(3 rows) + +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv ORDER BY v1; + v1 | v2 +------+----- + 10 | 100 + 11 | 100 + 1020 | 200 + 1020 | 222 +(4 rows) + +ROLLBACK; +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +NOTICE: created index "mv_ri_index" on materialized view "mv_ri" +SELECT * FROM mv_ri ORDER BY i1; + i1 | i2 +----+---- + 1 | 1 + 2 | 2 + 3 | 3 +(3 rows) + +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; + i1 | i2 +----+---- + 3 | 3 + 10 | 10 +(2 rows) + +ROLLBACK; +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | +(2 rows) + +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | 20 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i +--- +(0 rows) + +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; + i +--- + 1 + +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 30 + | 3 +(2 rows) + +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; + i | sum +---+----- + 1 | 300 + | 30 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +NOTICE: created index "mv_index" on materialized view "mv" +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 1 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 5 +(1 row) + +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; + i | min | max +---+-----+----- + | 2 | 4 +(1 row) + +ROLLBACK; +-- IMMV containing user defined type +BEGIN; +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: return type mytype is only a shell +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: argument type mytype is only a shell +LINE 1: CREATE FUNCTION mytype_out(mytype) + ^ +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +NOTICE: could not create an index on materialized view "mv_mytype" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + x +--- + 1 +(1 row) + +ROLLBACK; +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +ERROR: OUTER JOIN is not supported on incrementally maintainable materialized view +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +ERROR: CTE is not supported on incrementally maintainable materialized view +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +ERROR: ORDER BY clause is not supported on incrementally maintainable materialized view +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; +ERROR: HAVING clause is not supported on incrementally maintainable materialized view +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; +ERROR: mutable function is not supported on incrementally maintainable materialized view +HINT: functions must be marked IMMUTABLE +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; +ERROR: LIMIT/OFFSET clause is not supported on incrementally maintainable materialized view +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; +ERROR: DISTINCT ON is not supported on incrementally maintainable materialized view +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); +ERROR: TABLESAMPLE clause is not supported on incrementally maintainable materialized view +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; +ERROR: window functions are not supported on incrementally maintainable materialized view +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +ERROR: aggregate function with FILTER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +ERROR: aggregate function with DISTINCT arguments is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +ERROR: aggregate function with ORDER clause is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); +ERROR: GROUPING SETS, ROLLUP, or CUBE clauses is not supported on incrementally maintainable materialized view +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ERROR: inheritance parent is not supported on incrementally maintainable materialized view +ROLLBACK; +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; +ERROR: UNION/INTERSECT/EXCEPT statements are not supported on incrementally maintainable materialized view +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; +ERROR: empty target list is not supported on incrementally maintainable materialized view +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; +ERROR: FOR UPDATE/SHARE clause is not supported on incrementally maintainable materialized view +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; +ERROR: column name __ivm_count__ is not supported on incrementally maintainable materialized view +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; +ERROR: GROUP BY expression not appearing in select list is not supported on incrementally maintainable materialized view +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; +ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); +ERROR: VALUES is not supported on incrementally maintainable materialized view +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +NOTICE: role "regress_ivm_admin" does not exist, skipping +DROP USER IF EXISTS regress_ivm_user; +NOTICE: role "regress_ivm_user" does not exist, skipping +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +NOTICE: could not create an index on materialized view "ivm_rls" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user +(1 row) + +RESET SESSION AUTHORIZATION; +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user + 3 | baz | regress_ivm_user +(2 rows) + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +-- +(1 row) + +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+-------+------------------ + 2 | bar | regress_ivm_user + 3 | baz | regress_ivm_user + 6 | corge | regress_ivm_user +(3 rows) + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +NOTICE: could not create an index on materialized view "ivm_rls2" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +RESET SESSION AUTHORIZATION; +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +-- +(1 row) + +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + id | data | owner | num +----+-------+------------------+--------- + 2 | bar | regress_ivm_user | two + 3 | baz_2 | regress_ivm_user | three_2 + 6 | corge | regress_ivm_user | six +(3 rows) + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +NOTICE: could not create an index on materialized view "mv_update_same" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + i +--- + 2 +(1 row) + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +NOTICE: created index "mv_self_ref_index" on materialized view "mv_self_ref" +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; + a | b +----+---- + 11 | + 12 | 11 + 13 | 12 +(3 rows) + +ROLLBACK; +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; +NOTICE: created index "mv_idx1_index" on materialized view "mv_idx1" +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; +NOTICE: created index "mv_idx2_index" on materialized view "mv_idx2" +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; +NOTICE: created index "mv_idx3_index" on materialized view "mv_idx3" +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +NOTICE: could not create an index on materialized view "mv_idx4" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; +NOTICE: could not create an index on materialized view "mv_idx5" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); +NOTICE: could not create an index on materialized view "mv_idx6" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ERROR: data type json has no default operator class for access method "btree" +ROLLBACK; +-- cleanup +DROP TABLE rls_tbl CASCADE; +NOTICE: drop cascades to 2 other objects +DETAIL: drop cascades to materialized view ivm_rls +drop cascades to materialized view ivm_rls2 +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; +DROP TABLE mv_base_b CASCADE; +NOTICE: drop cascades to 3 other objects +DETAIL: drop cascades to materialized view mv_ivm_1 +drop cascades to view b_view +drop cascades to materialized view b_mview +DROP TABLE mv_base_a CASCADE; diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index 8fa0a6c47fb..7caca5f64fd 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -77,6 +77,7 @@ test: brin_bloom brin_multi # Another group of parallel tests # ---------- test: create_table_like alter_generic alter_operator misc async dbsize merge misc_functions nls sysviews tsrf tid tidscan tidrangescan collate.utf8 collate.icu.utf8 incremental_sort create_role without_overlaps generated_virtual +test: incremental_matview # collate.linux.utf8 and collate.icu.utf8 tests cannot be run in parallel with each other # psql depends on create_am diff --git a/src/test/regress/sql/incremental_matview.sql b/src/test/regress/sql/incremental_matview.sql new file mode 100644 index 00000000000..2d55c393d6f --- /dev/null +++ b/src/test/regress/sql/incremental_matview.sql @@ -0,0 +1,580 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); + +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +REFRESH MATERIALIZED VIEW mv_ivm_1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; + +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; +ROLLBACK; + +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- rename of IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_rename AS SELECT DISTINCT * FROM mv_base_a; +ALTER MATERIALIZED VIEW mv_ivm_rename RENAME COLUMN __ivm_count__ TO xxx; +DROP MATERIALIZED VIEW mv_ivm_rename; + +-- unique index on IVM columns +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_unique AS SELECT DISTINCT * FROM mv_base_a; +CREATE UNIQUE INDEX ON mv_ivm_unique(__ivm_count__); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__)); +CREATE UNIQUE INDEX ON mv_ivm_unique((__ivm_count__ + 1)); +DROP MATERIALIZED VIEW mv_ivm_unique; + +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; + + +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +ROLLBACK; + +-- result of materialized view have DISTINCT clause or the duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT j FROM mv_base_a; +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +SELECT * FROM mv_ivm_distinct ORDER BY 1; +ROLLBACK; + +-- support SUM(), COUNT() and AVG() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +UPDATE mv_base_a SET j = 200 WHERE (i,j) = (2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +DELETE FROM mv_base_a WHERE (i,j) = (2,200); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4; +ROLLBACK; + +-- support COUNT(*) aggregate function +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES(2,100); +SELECT * FROM mv_ivm_agg ORDER BY 1,2,3; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +TRUNCATE mv_base_a; +SELECT sum, count FROM mv_ivm_agg; +SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +INSERT INTO mv_base_a VALUES(6,60); +SELECT * FROM mv_ivm_group ORDER BY 1; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_group ORDER BY 1; +ROLLBACK; + +-- TRUNCATE a base table in aggregate views without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_group AS SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +TRUNCATE mv_base_a; +SELECT sum, count, avg FROM mv_ivm_group; +SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a; +ROLLBACK; + +-- resolved issue: When use AVG() function and values is indivisible, result of AVG() is incorrect. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_avg_bug AS SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i; +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,0), + (1,0), + (2,30), + (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) = (1,0); +DELETE FROM mv_base_a WHERE (i,j) = (2,30); +SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i; +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +INSERT INTO mv_base_a VALUES + (1,11), (1,12), + (2,21), (2,22), + (3,31), (3,32), + (4,41), (4,42), + (5,51), (5,52); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +DELETE FROM mv_base_a WHERE (i,j) IN ((1,10), (2,21), (3,32)); +SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3; +ROLLBACK; + +-- support MIN(), MAX() aggregate functions without GROUP clause +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min_max AS SELECT MIN(j), MAX(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +INSERT INTO mv_base_a VALUES + (0,0), (6,60), (7,70); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70)); +SELECT * FROM mv_ivm_min_max; +DELETE FROM mv_base_a; +SELECT * FROM mv_ivm_min_max; +ROLLBACK; + +-- Test MIN/MAX after search_path change +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_min AS SELECT MIN(j) FROM mv_base_a; +SELECT * FROM mv_ivm_min; + +CREATE SCHEMA myschema; +GRANT ALL ON SCHEMA myschema TO public; +CREATE TABLE myschema.mv_base_a (j int); +INSERT INTO myschema.mv_base_a VALUES (1); + +DELETE FROM mv_base_a WHERE (i,j) = (1,10); +SELECT * FROM mv_ivm_min; + +SET search_path TO myschema,public,pg_catalog; +DELETE FROM public.mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_min; +ROLLBACK; + +-- aggregate views with column names specified +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +INSERT INTO mv_base_a VALUES (1,100), (2,200), (3,300); +UPDATE mv_base_a SET j = 2000 WHERE (i,j) = (2,20); +DELETE FROM mv_base_a WHERE (i,j) = (3,30); +SELECT * FROM mv_ivm_agg ORDER BY 1,2; +ROLLBACK; +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg(a,b,c) AS SELECT i, SUM(j) FROM mv_base_a GROUP BY i; +ROLLBACK; + +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +SELECT * FROM mv_self ORDER BY v1; +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; +SELECT * FROM mv_self ORDER BY v1; + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + +ROLLBACK; + +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +SELECT * FROM mv ORDER BY v1; +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; +SELECT * FROM mv ORDER BY v1; +ROLLBACK; + +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +SELECT * FROM mv_ri ORDER BY i1; +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; +ROLLBACK; + +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (1, 10), (1, 20); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, sum(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = v * 10; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (NULL, 1), (NULL, 2), (NULL, 3), (NULL, 4), (NULL, 5); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT i, min(v), max(v) FROM base_t GROUP BY i; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 1; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 3; +SELECT * FROM mv ORDER BY i; +DELETE FROM base_t WHERE v = 5; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +-- IMMV containing user defined type +BEGIN; + +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); + +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; + +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); + +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); + +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + +ROLLBACK; + +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; + +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; + +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; + +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; + +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; + +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); + +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; + +-- aggregate function with some options is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm17 AS SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm18 AS SELECT COUNT(DISTINCT i) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm19 AS SELECT array_agg(j ORDER BY i DESC) FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm20 AS SELECT i,SUM(j) FROM mv_base_a GROUP BY GROUPING SETS((i),()); + +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ROLLBACK; + +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; + +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; + +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; + +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; + +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; + +-- experssions containing an aggregate is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm30 AS SELECT sum(i)*0.5 FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm31 AS SELECT sum(i)/sum(j) FROM mv_base_a; + +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); + +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +DROP USER IF EXISTS regress_ivm_user; +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; + +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); + +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; + +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; + +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; +RESET SESSION AUTHORIZATION; + +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +RESET SESSION AUTHORIZATION; + +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; +ROLLBACK; + +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); + +--- group by: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx1 AS SELECT i, sum(j) FROM base_a GROUP BY i; + +--- distinct: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx2 AS SELECT DISTINCT j FROM base_a; + +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; + +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; + +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); + +ROLLBACK; + +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ROLLBACK; + +-- cleanup + +DROP TABLE rls_tbl CASCADE; +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; + +DROP TABLE mv_base_b CASCADE; +DROP TABLE mv_base_a CASCADE; -- 2.43.0 --Multipart=_Wed__1_Jul_2026_00_04_01_+0900_OVSy2WWK_9aByzDJ Content-Type: text/x-diff; name="v38-0009-Add-support-for-min-max-aggregates-for-IVM.patch" Content-Disposition: attachment; filename="v38-0009-Add-support-for-min-max-aggregates-for-IVM.patch" Content-Transfer-Encoding: 7bit ^ permalink raw reply [nested|flat] 78+ messages in thread
* [PATCH v39 7/8] Add regression tests for Incremental View Maintenance @ 2026-05-29 09:31 Yugo Nagata <[email protected]> 0 siblings, 0 replies; 78+ messages in thread From: Yugo Nagata @ 2026-05-29 09:31 UTC (permalink / raw) --- .../isolation/expected/ivm-create-insert.out | 285 ++++++++ .../isolation/expected/ivm-create-insert2.out | 305 ++++++++ .../isolation/expected/ivm-create-insert3.out | 305 ++++++++ .../isolation/expected/ivm-insert-insert.out | 497 +++++++++++++ .../isolation/expected/ivm-insert-insert2.out | 373 ++++++++++ .../isolation/expected/ivm-insert-insert3.out | 373 ++++++++++ .../isolation/expected/ivm-refresh-insert.out | 213 ++++++ .../expected/ivm-refresh-insert2.out | 191 +++++ .../expected/ivm-refresh-insert3.out | 191 +++++ src/test/isolation/isolation_schedule | 9 + .../isolation/specs/ivm-create-insert.spec | 47 ++ .../isolation/specs/ivm-create-insert2.spec | 54 ++ .../isolation/specs/ivm-create-insert3.spec | 54 ++ .../isolation/specs/ivm-insert-insert.spec | 62 ++ .../isolation/specs/ivm-insert-insert2.spec | 62 ++ .../isolation/specs/ivm-insert-insert3.spec | 62 ++ .../isolation/specs/ivm-refresh-insert.spec | 46 ++ .../isolation/specs/ivm-refresh-insert2.spec | 46 ++ .../isolation/specs/ivm-refresh-insert3.spec | 46 ++ .../regress/expected/incremental_matview.out | 667 ++++++++++++++++++ src/test/regress/parallel_schedule | 1 + src/test/regress/sql/incremental_matview.sql | 407 +++++++++++ 22 files changed, 4296 insertions(+) create mode 100644 src/test/isolation/expected/ivm-create-insert.out create mode 100644 src/test/isolation/expected/ivm-create-insert2.out create mode 100644 src/test/isolation/expected/ivm-create-insert3.out create mode 100644 src/test/isolation/expected/ivm-insert-insert.out create mode 100644 src/test/isolation/expected/ivm-insert-insert2.out create mode 100644 src/test/isolation/expected/ivm-insert-insert3.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert2.out create mode 100644 src/test/isolation/expected/ivm-refresh-insert3.out create mode 100644 src/test/isolation/specs/ivm-create-insert.spec create mode 100644 src/test/isolation/specs/ivm-create-insert2.spec create mode 100644 src/test/isolation/specs/ivm-create-insert3.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert2.spec create mode 100644 src/test/isolation/specs/ivm-insert-insert3.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert2.spec create mode 100644 src/test/isolation/specs/ivm-refresh-insert3.spec create mode 100644 src/test/regress/expected/incremental_matview.out create mode 100644 src/test/regress/sql/incremental_matview.sql diff --git a/src/test/isolation/expected/ivm-create-insert.out b/src/test/isolation/expected/ivm-create-insert.out new file mode 100644 index 00000000000..5da00043aba --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert.out @@ -0,0 +1,285 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-create-insert2.out b/src/test/isolation/expected/ivm-create-insert2.out new file mode 100644 index 00000000000..907d892c6d4 --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert2.out @@ -0,0 +1,305 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + diff --git a/src/test/isolation/expected/ivm-create-insert3.out b/src/test/isolation/expected/ivm-create-insert3.out new file mode 100644 index 00000000000..907d892c6d4 --- /dev/null +++ b/src/test/isolation/expected/ivm-create-insert3.out @@ -0,0 +1,305 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 create s2 insert c1 check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 create s2 c1 insert check2 c2 mv +step s1: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 create insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert create c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s1 s2 create c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 create c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + <waiting ...> +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 insert s1 c2 create check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + + +starting permutation: s2 s1 insert c2 create check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +tx1: NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause. +HINT: Create an index on the materialized view for efficient incremental maintenance. +tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ +DETAIL: The view may not include effects of a concurrent transaction. +HINT: The view with incremental maintenance should be created in isolation level READ COMMITTED, or refreshed manually to make sure the view is consistent. +step create: + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; + +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ng +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert.out b/src/test/isolation/expected/ivm-insert-insert.out new file mode 100644 index 00000000000..5ca4cfea677 --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert.out @@ -0,0 +1,497 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; <waiting ...> +step c1: COMMIT; +step update2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; <waiting ...> +step c1: COMMIT; +step update2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; <waiting ...> +step c2: COMMIT; +step update1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; <waiting ...> +step c2: COMMIT; +step update1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); <waiting ...> +step c1: COMMIT; +step insert2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); <waiting ...> +step c1: COMMIT; +step insert2: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); <waiting ...> +step c2: COMMIT; +step insert1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); <waiting ...> +step c2: COMMIT; +step insert1: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +20|20|200 +20|20|201 +20|21|200 +20|21|201 +21|20|200 +21|20|201 +21|21|200 +21|21|201 +(12 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert2.out b/src/test/isolation/expected/ivm-insert-insert2.out new file mode 100644 index 00000000000..e1c66d4de5e --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert2.out @@ -0,0 +1,373 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-insert-insert3.out b/src/test/isolation/expected/ivm-insert-insert3.out new file mode 100644 index 00000000000..e1c66d4de5e --- /dev/null +++ b/src/test/isolation/expected/ivm-insert-insert3.out @@ -0,0 +1,373 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 update1 s2 update2 c1 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 update1 s2 c1 update2 check2 c2 mv +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step s2: SELECT; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 update2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update2 update1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 update1 c1 update2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +step c1: COMMIT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +11|11|100 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 update1 c2 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 update2 s1 c2 update1 check1 c1 mv +step s2: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step s1: SELECT; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 update2 c2 update1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step update2: UPDATE b SET j = 111 WHERE i = 1; +step c2: COMMIT; +step update1: UPDATE a SET j = 11 WHERE i = 1; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|111 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step s2: SELECT; +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +step c1: COMMIT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +20|20|200 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c2: COMMIT; +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv +step s2: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step s1: SELECT; +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); +step c2: COMMIT; +step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); + x| y| z +--+--+--- +10|10|100 +10|11|100 +11|10|100 +11|11|100 +21|21|201 +(5 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert.out b/src/test/isolation/expected/ivm-refresh-insert.out new file mode 100644 index 00000000000..a925938bf1c --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert.out @@ -0,0 +1,213 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); <waiting ...> +step c1: COMMIT; +step insert: <... completed> +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step check1: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert2.out b/src/test/isolation/expected/ivm-refresh-insert2.out new file mode 100644 index 00000000000..dc1b16ae34e --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert2.out @@ -0,0 +1,191 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/expected/ivm-refresh-insert3.out b/src/test/isolation/expected/ivm-refresh-insert3.out new file mode 100644 index 00000000000..dc1b16ae34e --- /dev/null +++ b/src/test/isolation/expected/ivm-refresh-insert3.out @@ -0,0 +1,191 @@ +Parsed test spec with 2 sessions + +starting permutation: s1 refresh s2 insert c1 check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 refresh s2 c1 insert check2 c2 mv +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step s2: SELECT; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh insert c1 check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step insert: INSERT INTO a VALUES (2); +ERROR: could not obtain lock on materialized view "mv" during incremental maintenance +step c1: COMMIT; +step check2: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +(1 row) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 insert refresh c2 check1 c1 mv +step s1: SELECT; +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s1 s2 refresh c1 insert check2 c2 mv +step s1: SELECT; +step s2: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; +step c1: COMMIT; +step insert: INSERT INTO a VALUES (2); +step check2: SELECT check_mv(); +check_mv +-------- +ok +(1 row) + +step c2: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 refresh c2 check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step refresh: REFRESH MATERIALIZED VIEW mv; <waiting ...> +step c2: COMMIT; +step refresh: <... completed> +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 insert s1 c2 refresh check1 c1 mv +step s2: SELECT; +step insert: INSERT INTO a VALUES (2); +step s1: SELECT; +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + + +starting permutation: s2 s1 insert c2 refresh check1 c1 mv +step s2: SELECT; +step s1: SELECT; +step insert: INSERT INTO a VALUES (2); +step c2: COMMIT; +step refresh: REFRESH MATERIALIZED VIEW mv; +ERROR: the materialized view is incrementally updated in concurrent transaction +step check1: SELECT check_mv(); +ERROR: current transaction is aborted, commands ignored until end of transaction block +step c1: COMMIT; +step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); +x|y +-+- +1|1 +2|2 +(2 rows) + +check_mv +-------- +ok +(1 row) + diff --git a/src/test/isolation/isolation_schedule b/src/test/isolation/isolation_schedule index b8ebe92553c..6b7e873b370 100644 --- a/src/test/isolation/isolation_schedule +++ b/src/test/isolation/isolation_schedule @@ -128,3 +128,12 @@ test: matview-write-skew test: lock-nowait test: for-portion-of test: ddl-dependency-locking +test: ivm-create-insert +test: ivm-create-insert2 +test: ivm-create-insert3 +test: ivm-insert-insert +test: ivm-insert-insert2 +test: ivm-insert-insert3 +test: ivm-refresh-insert +test: ivm-refresh-insert2 +test: ivm-refresh-insert3 diff --git a/src/test/isolation/specs/ivm-create-insert.spec b/src/test/isolation/specs/ivm-create-insert.spec new file mode 100644 index 00000000000..ccd6fd080a9 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert.spec @@ -0,0 +1,47 @@ +# Test interaction between concurrent transactions performing +# create and insert in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-create-insert2.spec b/src/test/isolation/specs/ivm-create-insert2.spec new file mode 100644 index 00000000000..02cec85ae07 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert2.spec @@ -0,0 +1,54 @@ +# Test interaction between concurrent transactions performing +# create and insert in REPEATABLE READ isolation level +# +# Note: +# In this isolation level, it is possible that create_immv could +# create an inconsistent view not including effects of a concurrent +# transaction. So, an warning message is raised to suggest using it +# in READ COMMITTED or executing refresh_immv to make sure to +# make the view contents consistent. + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-create-insert3.spec b/src/test/isolation/specs/ivm-create-insert3.spec new file mode 100644 index 00000000000..19ce03185a4 --- /dev/null +++ b/src/test/isolation/specs/ivm-create-insert3.spec @@ -0,0 +1,54 @@ +# Test interaction between concurrent transactions performing +# create and insert in SERIALIZABLE isolation level +# +# Note: +# In this isolation level, it is possible that create_immv could +# create an inconsistent view not including effects of a concurrent +# transaction. So, an warning message is raised to suggest using it +# in READ COMMITTED or executing refresh_immv to make sure to +# make the view contents consistent. + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step create { + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 create s2 insert c1 check2 c2 mv +permutation s1 create s2 c1 insert check2 c2 mv +permutation s1 s2 create insert c1 check2 c2 mv +permutation s1 s2 insert create c2 check1 c1 mv +permutation s1 s2 create c1 insert check2 c2 mv +permutation s2 insert s1 create c2 check1 c1 mv +permutation s2 insert s1 c2 create check1 c1 mv +permutation s2 s1 insert c2 create check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert.spec b/src/test/isolation/specs/ivm-insert-insert.spec new file mode 100644 index 00000000000..b8f794ca191 --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert2.spec b/src/test/isolation/specs/ivm-insert-insert2.spec new file mode 100644 index 00000000000..ed086d1ba1e --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert2.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in REPEATABLE READ isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-insert-insert3.spec b/src/test/isolation/specs/ivm-insert-insert3.spec new file mode 100644 index 00000000000..b18bd121033 --- /dev/null +++ b/src/test/isolation/specs/ivm-insert-insert3.spec @@ -0,0 +1,62 @@ +# Test interaction between concurrent transactions performing +# table modifications in SERIALIZABLE isolation level + +setup +{ + CREATE TABLE a (i int, j int); + CREATE TABLE b (i int, j int); + INSERT INTO a VALUES (1,10); + INSERT INTO b VALUES (1,100); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE VIEW v(x,y,z) AS + SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; + DROP TABLE b; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); } +step update1 { UPDATE a SET j = 11 WHERE i = 1; } +step check1 { SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); } +step update2 { UPDATE b SET j = 111 WHERE i = 1; } +step check2 { SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 update1 s2 update2 c1 check2 c2 mv +permutation s1 update1 s2 c1 update2 check2 c2 mv +permutation s1 s2 update1 update2 c1 check2 c2 mv +permutation s1 s2 update2 update1 c2 check1 c1 mv +permutation s1 s2 update1 c1 update2 check2 c2 mv +permutation s2 update2 s1 update1 c2 check1 c1 mv +permutation s2 update2 s1 c2 update1 check1 c1 mv +permutation s2 s1 update2 c2 update1 check1 c1 mv + +permutation s1 insert1 s2 insert2 c1 check2 c2 mv +permutation s1 insert1 s2 c1 insert2 check2 c2 mv +permutation s1 s2 insert1 insert2 c1 check2 c2 mv +permutation s1 s2 insert2 insert1 c2 check1 c1 mv +permutation s1 s2 insert1 c1 insert2 check2 c2 mv +permutation s2 insert2 s1 insert1 c2 check1 c1 mv +permutation s2 insert2 s1 c2 insert1 check1 c1 mv +permutation s2 s1 insert2 c2 insert1 check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert.spec b/src/test/isolation/specs/ivm-refresh-insert.spec new file mode 100644 index 00000000000..d7181251962 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in READ COMMITTED isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert2.spec b/src/test/isolation/specs/ivm-refresh-insert2.spec new file mode 100644 index 00000000000..f2d1d5013f2 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert2.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in REPEATABLE READ isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/isolation/specs/ivm-refresh-insert3.spec b/src/test/isolation/specs/ivm-refresh-insert3.spec new file mode 100644 index 00000000000..0ec2b1d1de0 --- /dev/null +++ b/src/test/isolation/specs/ivm-refresh-insert3.spec @@ -0,0 +1,46 @@ +# Test interaction between concurrent transactions performing +# refresh and insert in SERIALIZABLE isolation level + +setup +{ + CREATE TABLE a (i int); + INSERT INTO a VALUES (1); + CREATE INCREMENTAL MATERIALIZED VIEW mv(x,y) AS SELECT * FROM a a1, a a2 WHERE a1.i = a2.i; + CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i; + CREATE FUNCTION check_mv() RETURNS text AS + $$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END + FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL + (SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) v $$ LANGUAGE sql; +} + +teardown +{ + DROP FUNCTION check_mv(); + DROP MATERIALIZED VIEW mv; + DROP VIEW v; + DROP TABLE a; +} + +session tx1 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s1 { SELECT; } +step refresh { REFRESH MATERIALIZED VIEW mv; } +step check1 {SELECT check_mv();} +step c1 { COMMIT; } +step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); } + +session tx2 +setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; } +step s2 { SELECT; } +step insert { INSERT INTO a VALUES (2); } +step check2 {SELECT check_mv(); } +step c2 { COMMIT; } + +permutation s1 refresh s2 insert c1 check2 c2 mv +permutation s1 refresh s2 c1 insert check2 c2 mv +permutation s1 s2 refresh insert c1 check2 c2 mv +permutation s1 s2 insert refresh c2 check1 c1 mv +permutation s1 s2 refresh c1 insert check2 c2 mv +permutation s2 insert s1 refresh c2 check1 c1 mv +permutation s2 insert s1 c2 refresh check1 c1 mv +permutation s2 s1 insert c2 refresh check1 c1 mv diff --git a/src/test/regress/expected/incremental_matview.out b/src/test/regress/expected/incremental_matview.out new file mode 100644 index 00000000000..c7fd19fdca3 --- /dev/null +++ b/src/test/regress/expected/incremental_matview.out @@ -0,0 +1,667 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ERROR: materialized view "mv_ivm_1" has not been populated +HINT: Use the REFRESH MATERIALIZED VIEW command. +REFRESH MATERIALIZED VIEW mv_ivm_1; +NOTICE: could not create an index on materialized view "mv_ivm_1" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 17 +(1 row) + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + count +------- + 1 +(1 row) + +ROLLBACK; +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 + 5 | 50 | 105 +(5 rows) + +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 10 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +-- DISTINCT not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT * FROM mv_base_a; +ERROR: DISTINCT is not supported on incrementally maintainable materialized view +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + i | j | k +---+----+----- + 1 | 0 | 101 + 2 | 20 | 102 + 3 | 30 | 103 + 4 | 40 | 104 +(4 rows) + +ROLLBACK; +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; + i | j | k +---+---+--- +(0 rows) + +ROLLBACK; +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +NOTICE: could not create an index on materialized view "mv_ivm_func" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +NOTICE: could not create an index on materialized view "mv_ivm_no_tbl" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- result of materialized view have duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +NOTICE: could not create an index on materialized view "mv_ivm_duplicate" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 20 + 30 + 40 + 50 +(6 rows) + +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; + j +---- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +ROLLBACK; +-- aggregate not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; +ERROR: aggregate function is not supported on incrementally maintainable materialized view +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +NOTICE: could not create an index on materialized view "mv_self" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +----+---- + 10 | 10 + 20 | 20 + 30 | 30 +(3 rows) + +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 30 | 30 + 40 | 40 + 200 | 200 +(3 rows) + +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv_self ORDER BY v1; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 130 | 130 + 300 | 300 +(4 rows) + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + v1 | v2 +-----+----- + 50 | 50 + 60 | 60 + 70 | 70 + 70 | 77 + 77 | 70 + 77 | 77 + 130 | 130 + 300 | 300 +(8 rows) + +ROLLBACK; +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY v1; + v1 | v2 +----+----- + 10 | 100 + 20 | 200 + 30 | 300 +(3 rows) + +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; + ?column? +---------- + +(1 row) + +SELECT * FROM mv ORDER BY v1; + v1 | v2 +------+----- + 10 | 100 + 11 | 100 + 1020 | 200 + 1020 | 222 +(4 rows) + +ROLLBACK; +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +NOTICE: created index "mv_ri_index" on materialized view "mv_ri" +SELECT * FROM mv_ri ORDER BY i1; + i1 | i2 +----+---- + 1 | 1 + 2 | 2 + 3 | 3 +(3 rows) + +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; + i1 | i2 +----+---- + 3 | 3 + 10 | 10 +(2 rows) + +ROLLBACK; +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | +(2 rows) + +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; + i | v +---+---- + 1 | 10 + 2 | 20 +(2 rows) + +ROLLBACK; +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +NOTICE: could not create an index on materialized view "mv" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT * FROM mv ORDER BY i; + i +--- +(0 rows) + +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; + i +--- + 1 + +(2 rows) + +ROLLBACK; +-- IMMV containing user defined type +BEGIN; +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: return type mytype is only a shell +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +NOTICE: argument type mytype is only a shell +LINE 1: CREATE FUNCTION mytype_out(mytype) + ^ +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +NOTICE: could not create an index on materialized view "mv_mytype" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + x +--- + 1 +(1 row) + +ROLLBACK; +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +ERROR: OUTER JOIN is not supported on incrementally maintainable materialized view +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +ERROR: CTE is not supported on incrementally maintainable materialized view +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +ERROR: system column is not supported on incrementally maintainable materialized view +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +ERROR: ORDER BY clause is not supported on incrementally maintainable materialized view +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; +ERROR: HAVING clause is not supported on incrementally maintainable materialized view +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +ERROR: VIEW or MATERIALIZED VIEW is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +ERROR: subquery is not supported on incrementally maintainable materialized view +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; +ERROR: subquery is not supported on incrementally maintainable materialized view +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; +ERROR: mutable function is not supported on incrementally maintainable materialized view +HINT: functions must be marked IMMUTABLE +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; +ERROR: LIMIT/OFFSET clause is not supported on incrementally maintainable materialized view +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; +ERROR: DISTINCT is not supported on incrementally maintainable materialized view +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); +ERROR: TABLESAMPLE clause is not supported on incrementally maintainable materialized view +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; +ERROR: window functions are not supported on incrementally maintainable materialized view +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ERROR: inheritance parent is not supported on incrementally maintainable materialized view +ROLLBACK; +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; +ERROR: UNION/INTERSECT/EXCEPT statements are not supported on incrementally maintainable materialized view +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; +ERROR: empty target list is not supported on incrementally maintainable materialized view +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; +ERROR: FOR UPDATE/SHARE clause is not supported on incrementally maintainable materialized view +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; +ERROR: column name __ivm_count__ is not supported on incrementally maintainable materialized view +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; +ERROR: aggregate function is not supported on incrementally maintainable materialized view +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); +ERROR: VALUES is not supported on incrementally maintainable materialized view +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +NOTICE: role "regress_ivm_admin" does not exist, skipping +DROP USER IF EXISTS regress_ivm_user; +NOTICE: role "regress_ivm_user" does not exist, skipping +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +NOTICE: could not create an index on materialized view "ivm_rls" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user +(1 row) + +RESET SESSION AUTHORIZATION; +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+------+------------------ + 1 | foo | regress_ivm_user + 3 | baz | regress_ivm_user +(2 rows) + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +-- +(1 row) + +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + id | data | owner +----+-------+------------------ + 2 | bar | regress_ivm_user + 3 | baz | regress_ivm_user + 6 | corge | regress_ivm_user +(3 rows) + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +NOTICE: could not create an index on materialized view "ivm_rls2" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +RESET SESSION AUTHORIZATION; +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +-- +(1 row) + +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + id | data | owner | num +----+-------+------------------+--------- + 2 | bar | regress_ivm_user | two + 3 | baz_2 | regress_ivm_user | three_2 + 6 | corge | regress_ivm_user | six +(3 rows) + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +NOTICE: could not create an index on materialized view "mv_update_same" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + i +--- + 2 +(1 row) + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +NOTICE: created index "mv_self_ref_index" on materialized view "mv_self_ref" +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; + a | b +----+---- + 11 | + 12 | 11 + 13 | 12 +(3 rows) + +ROLLBACK; +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; +NOTICE: created index "mv_idx3_index" on materialized view "mv_idx3" +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +NOTICE: could not create an index on materialized view "mv_idx4" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; +NOTICE: could not create an index on materialized view "mv_idx5" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); +NOTICE: could not create an index on materialized view "mv_idx6" automatically +DETAIL: This target list does not have all the primary key columns. +HINT: Create an index on the materialized view for efficient incremental maintenance. +ROLLBACK; +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ERROR: data type json has no default operator class for access method "btree" +ROLLBACK; +-- cleanup +DROP TABLE rls_tbl CASCADE; +NOTICE: drop cascades to 2 other objects +DETAIL: drop cascades to materialized view ivm_rls +drop cascades to materialized view ivm_rls2 +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; +DROP TABLE mv_base_b CASCADE; +NOTICE: drop cascades to 3 other objects +DETAIL: drop cascades to materialized view mv_ivm_1 +drop cascades to view b_view +drop cascades to materialized view b_mview +DROP TABLE mv_base_a CASCADE; diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index 8fa0a6c47fb..7caca5f64fd 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -77,6 +77,7 @@ test: brin_bloom brin_multi # Another group of parallel tests # ---------- test: create_table_like alter_generic alter_operator misc async dbsize merge misc_functions nls sysviews tsrf tid tidscan tidrangescan collate.utf8 collate.icu.utf8 incremental_sort create_role without_overlaps generated_virtual +test: incremental_matview # collate.linux.utf8 and collate.icu.utf8 tests cannot be run in parallel with each other # psql depends on create_am diff --git a/src/test/regress/sql/incremental_matview.sql b/src/test/regress/sql/incremental_matview.sql new file mode 100644 index 00000000000..7313ad82f3e --- /dev/null +++ b/src/test/regress/sql/incremental_matview.sql @@ -0,0 +1,407 @@ +-- create a table to use as a basis for views and materialized views in various combinations +CREATE TABLE mv_base_a (x int, i int, y int, j int); +CREATE TABLE mv_base_b (x int, i int, y int, k int); +-- test for base tables with dropped columns +ALTER TABLE mv_base_a DROP COLUMN x; +ALTER TABLE mv_base_a DROP COLUMN y; +ALTER TABLE mv_base_b DROP COLUMN x; +ALTER TABLE mv_base_b DROP COLUMN y; +INSERT INTO mv_base_a VALUES + (1,10), + (2,20), + (3,30), + (4,40), + (5,50); +INSERT INTO mv_base_b VALUES + (1,101), + (2,102), + (3,103), + (4,104); + +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_1 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) WITH NO DATA; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +REFRESH MATERIALIZED VIEW mv_ivm_1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- REFRESH WITH NO DATA +BEGIN; +CREATE FUNCTION dummy_ivm_trigger_func() RETURNS TRIGGER AS $$ + BEGIN + RETURN NULL; + END +$$ language plpgsql; + +CREATE CONSTRAINT TRIGGER dummy_ivm_trigger AFTER INSERT +ON mv_base_a FROM mv_ivm_1 FOR EACH ROW +EXECUTE PROCEDURE dummy_ivm_trigger_func(); + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; + +REFRESH MATERIALIZED VIEW mv_ivm_1 WITH NO DATA; + +SELECT COUNT(*) +FROM pg_depend pd INNER JOIN pg_trigger pt ON pd.objid = pt.oid +WHERE pd.classid = 'pg_trigger'::regclass AND pd.refobjid = 'mv_ivm_1'::regclass; +ROLLBACK; + +-- immediate maintenance +BEGIN; +INSERT INTO mv_base_b VALUES(5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +UPDATE mv_base_a SET j = 0 WHERE i = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +DELETE FROM mv_base_b WHERE (i,k) = (5,105); +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; + +-- DISTINCT not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_distinct AS SELECT DISTINCT * FROM mv_base_a; + +-- test for renaming column name to camel style +BEGIN; +ALTER TABLE mv_base_a RENAME i TO "I"; +ALTER TABLE mv_base_a RENAME j TO "J"; +UPDATE mv_base_a SET "J" = 0 WHERE "I" = 1; +SELECT * FROM mv_ivm_1 ORDER BY 1,2,3; +ROLLBACK; + + +-- TRUNCATE a base table in join views +BEGIN; +TRUNCATE mv_base_a; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +BEGIN; +TRUNCATE mv_base_b; +SELECT * FROM mv_ivm_1; +ROLLBACK; + +-- some query syntax +BEGIN; +CREATE FUNCTION ivm_func() RETURNS int LANGUAGE 'sql' + AS 'SELECT 1' IMMUTABLE; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_func AS SELECT * FROM ivm_func(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_no_tbl AS SELECT 1; +ROLLBACK; + +-- result of materialized view have duplicate result. +BEGIN; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_duplicate AS SELECT j FROM mv_base_a; +INSERT INTO mv_base_a VALUES(6,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +DELETE FROM mv_base_a WHERE (i,j) = (2,20); +SELECT * FROM mv_ivm_duplicate ORDER BY 1; +ROLLBACK; + +-- aggregate not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_agg AS SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i; + +-- support self join view and multiple change on the same table +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self(v1, v2) AS + SELECT t1.v, t2.v FROM base_t AS t1 JOIN base_t AS t2 ON t1.i = t2.i; +SELECT * FROM mv_self ORDER BY v1; +INSERT INTO base_t VALUES (4,40); +DELETE FROM base_t WHERE i = 1; +UPDATE base_t SET v = v*10 WHERE i=2; +SELECT * FROM mv_self ORDER BY v1; +WITH + ins_t1 AS (INSERT INTO base_t VALUES (5,50) RETURNING 1), + ins_t2 AS (INSERT INTO base_t VALUES (6,60) RETURNING 1), + upd_t AS (UPDATE base_t SET v = v + 100 RETURNING 1), + dlt_t AS (DELETE FROM base_t WHERE i IN (4,5) RETURNING 1) +SELECT NULL; +SELECT * FROM mv_self ORDER BY v1; + +--- with sub-transactions +SAVEPOINT p1; +INSERT INTO base_t VALUES (7,70); +RELEASE SAVEPOINT p1; +INSERT INTO base_t VALUES (7,77); +SELECT * FROM mv_self ORDER BY v1, v2; + +ROLLBACK; + +-- support simultaneous table changes +BEGIN; +CREATE TABLE base_r (i int, v int); +CREATE TABLE base_s (i int, v int); +INSERT INTO base_r VALUES (1, 10), (2, 20), (3, 30); +INSERT INTO base_s VALUES (1, 100), (2, 200), (3, 300); +CREATE INCREMENTAL MATERIALIZED VIEW mv(v1, v2) AS + SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i); +SELECT * FROM mv ORDER BY v1; +WITH + ins_r AS (INSERT INTO base_r VALUES (1,11) RETURNING 1), + ins_r2 AS (INSERT INTO base_r VALUES (3,33) RETURNING 1), + ins_s AS (INSERT INTO base_s VALUES (2,222) RETURNING 1), + upd_r AS (UPDATE base_r SET v = v + 1000 WHERE i = 2 RETURNING 1), + dlt_s AS (DELETE FROM base_s WHERE i = 3 RETURNING 1) +SELECT NULL; +SELECT * FROM mv ORDER BY v1; +ROLLBACK; + +-- support foreign reference constraints +BEGIN; +CREATE TABLE ri1 (i int PRIMARY KEY); +CREATE TABLE ri2 (i int PRIMARY KEY REFERENCES ri1(i) ON UPDATE CASCADE ON DELETE CASCADE, v int); +INSERT INTO ri1 VALUES (1),(2),(3); +INSERT INTO ri2 VALUES (1),(2),(3); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ri(i1, i2) AS + SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i); +SELECT * FROM mv_ri ORDER BY i1; +UPDATE ri1 SET i=10 where i=1; +DELETE FROM ri1 WHERE i=2; +SELECT * FROM mv_ri ORDER BY i2; +ROLLBACK; + +-- views including NULL +BEGIN; +CREATE TABLE base_t (i int, v int); +INSERT INTO base_t VALUES (1,10),(2, NULL); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +UPDATE base_t SET v = 20 WHERE i = 2; +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +BEGIN; +CREATE TABLE base_t (i int); +CREATE INCREMENTAL MATERIALIZED VIEW mv AS SELECT * FROM base_t; +SELECT * FROM mv ORDER BY i; +INSERT INTO base_t VALUES (1),(NULL); +SELECT * FROM mv ORDER BY i; +ROLLBACK; + +-- IMMV containing user defined type +BEGIN; + +CREATE TYPE mytype; +CREATE FUNCTION mytype_in(cstring) + RETURNS mytype AS 'int4in' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_out(mytype) + RETURNS cstring AS 'int4out' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE TYPE mytype ( + LIKE = int4, + INPUT = mytype_in, + OUTPUT = mytype_out +); + +CREATE FUNCTION mytype_eq(mytype, mytype) + RETURNS bool AS 'int4eq' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_lt(mytype, mytype) + RETURNS bool AS 'int4lt' + LANGUAGE INTERNAL STRICT IMMUTABLE; +CREATE FUNCTION mytype_cmp(mytype, mytype) + RETURNS integer AS 'btint4cmp' + LANGUAGE INTERNAL STRICT IMMUTABLE; + +CREATE OPERATOR = ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_eq); +CREATE OPERATOR < ( + leftarg = mytype, rightarg = mytype, + procedure = mytype_lt); + +CREATE OPERATOR CLASS mytype_ops + DEFAULT FOR TYPE mytype USING btree AS + OPERATOR 1 <, + OPERATOR 3 = , + FUNCTION 1 mytype_cmp(mytype,mytype); + +CREATE TABLE t_mytype (x mytype); +CREATE INCREMENTAL MATERIALIZED VIEW mv_mytype AS + SELECT * FROM t_mytype; +INSERT INTO t_mytype VALUES ('1'::mytype); +SELECT * FROM mv_mytype; + +ROLLBACK; + +-- outer join is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv(a,b) AS SELECT a.i, b.i FROM mv_base_a a LEFT JOIN mv_base_b b ON a.i=b.i; +-- CTE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv AS + WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i; +-- contain system column +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm01 AS SELECT i,j,xmin FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm02 AS SELECT i,j FROM mv_base_a WHERE xmin = '610'; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT i,j,xmin::text AS x_min FROM mv_base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm06 AS SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a; +-- contain subquery +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm03 AS SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 ); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm04 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT * FROM mv_base_b) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm05 AS SELECT i,j, (SELECT k FROM mv_base_b b WHERE a.i = b.i) FROM mv_base_a a; +-- contain ORDER BY +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) ORDER BY i,j,k; +-- contain HAVING +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i) GROUP BY i,j,k HAVING SUM(i) > 5; + +-- contain view or materialized view +CREATE VIEW b_view AS SELECT i,k FROM mv_base_b; +CREATE MATERIALIZED VIEW b_mview AS SELECT i,k FROM mv_base_b; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm07 AS SELECT a.i,a.j FROM mv_base_a a,b_view b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm08 AS SELECT a.i,a.j FROM mv_base_a a,b_mview b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm09 AS SELECT a.i,a.j FROM mv_base_a a, (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) b WHERE a.i = b.i; +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm10 AS SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) OR a.i > 5; + +-- contain mutable functions +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm12 AS SELECT i,j FROM mv_base_a WHERE i = random()::int; + +-- LIMIT/OFFSET is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm13 AS SELECT i,j FROM mv_base_a LIMIT 10 OFFSET 5; + +-- DISTINCT ON is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm14 AS SELECT DISTINCT ON(i) i, j FROM mv_base_a; + +-- TABLESAMPLE clause is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm15 AS SELECT i, j FROM mv_base_a TABLESAMPLE SYSTEM(50); + +-- window functions are not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm16 AS SELECT *, cume_dist() OVER (ORDER BY i) AS rank FROM mv_base_a; + +-- inheritance parent is not supported +BEGIN; +CREATE TABLE parent (i int, v int); +CREATE TABLE child_a(options text) INHERITS(parent); +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm21 AS SELECT * FROM parent; +ROLLBACK; + +-- UNION statement is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm22 AS SELECT i,j FROM mv_base_a UNION ALL SELECT i,k FROM mv_base_b;; + +-- empty target list is not allowed with IVM +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm25 AS SELECT FROM mv_base_a; + +-- FOR UPDATE/SHARE is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm26 AS SELECT i,j FROM mv_base_a FOR UPDATE; + +-- tartget list cannot contain ivm column that start with '__ivm' +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm28 AS SELECT i AS "__ivm_count__" FROM mv_base_a; + +-- expressions specified in GROUP BY must appear in the target list. +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm29 AS SELECT COUNT(i) FROM mv_base_a GROUP BY i; + +-- VALUES is not supported +CREATE INCREMENTAL MATERIALIZED VIEW mv_ivm_only_values1 AS values(1); + +-- views containing base tables with Row Level Security +DROP USER IF EXISTS regress_ivm_admin; +DROP USER IF EXISTS regress_ivm_user; +CREATE USER regress_ivm_admin; +CREATE USER regress_ivm_user; + +--- create a table with RLS +SET SESSION AUTHORIZATION regress_ivm_admin; +CREATE TABLE rls_tbl(id int, data text, owner name); +INSERT INTO rls_tbl VALUES + (1,'foo','regress_ivm_user'), + (2,'bar','postgres'); +CREATE TABLE num_tbl(id int, num text); +INSERT INTO num_tbl VALUES + (1,'one'), + (2,'two'), + (3,'three'), + (4,'four'), + (5,'five'), + (6,'six'); + +--- Users can access only their own rows +CREATE POLICY rls_tbl_policy ON rls_tbl FOR SELECT TO PUBLIC USING(owner = current_user); +ALTER TABLE rls_tbl ENABLE ROW LEVEL SECURITY; +GRANT ALL on rls_tbl TO PUBLIC; +GRANT ALL on num_tbl TO PUBLIC; + +--- create a view owned by regress_ivm_user +SET SESSION AUTHORIZATION regress_ivm_user; + +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls AS SELECT * FROM rls_tbl; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; +RESET SESSION AUTHORIZATION; + +--- inserts rows owned by different users +INSERT INTO rls_tbl VALUES + (3,'baz','regress_ivm_user'), + (4,'qux','postgres'); +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- combination of diffent kinds of commands +WITH + i AS (INSERT INTO rls_tbl VALUES(5,'quux','postgres'), (6,'corge','regress_ivm_user')), + u AS (UPDATE rls_tbl SET owner = 'postgres' WHERE id = 1), + u2 AS (UPDATE rls_tbl SET owner = 'regress_ivm_user' WHERE id = 2) +SELECT; +SELECT id, data, owner FROM ivm_rls ORDER BY 1,2,3; + +--- +SET SESSION AUTHORIZATION regress_ivm_user; +CREATE INCREMENTAL MATERIALIZED VIEW ivm_rls2 AS SELECT * FROM rls_tbl JOIN num_tbl USING(id); +RESET SESSION AUTHORIZATION; + +WITH + x AS (UPDATE rls_tbl SET data = data || '_2' where id in (3,4)), + y AS (UPDATE num_tbl SET num = num || '_2' where id in (3,4)) +SELECT; +SELECT * FROM ivm_rls2 ORDER BY 1,2,3; + +-- trigger updating the same table +BEGIN; +CREATE TABLE tbl_update_same (i int); +CREATE FUNCTION func_update_same() RETURNS TRIGGER AS + $$ BEGIN UPDATE tbl_update_same SET i = i + 1; RETURN NEW; END; $$ + LANGUAGE plpgsql; +CREATE TRIGGER trig_update_same AFTER INSERT ON tbl_update_same FOR EACH ROW + EXECUTE FUNCTION func_update_same(); +CREATE INCREMENTAL MATERIALIZED VIEW mv_update_same AS SELECT * FROM tbl_update_same; +INSERT INTO tbl_update_same VALUES (1); +SELECT * FROM mv_update_same; + +-- self-referential FKs +CREATE TABLE tbl_self_ref (a int primary key, + b int references tbl_self_ref(a) ON UPDATE CASCADE); +INSERT INTO tbl_self_ref VALUES (1, null), (2, 1), (3, 2); +CREATE INCREMENTAL MATERIALIZED VIEW mv_self_ref AS SELECT * FROM tbl_self_ref; +UPDATE tbl_self_ref set a = a + 10; +SELECT * FROM mv_self_ref ORDER BY a; +ROLLBACK; + +-- automatic index creation +BEGIN; +CREATE TABLE base_a (i int primary key, j int); +CREATE TABLE base_b (i int primary key, j int); + +--- with all pkey columns: create an index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx3(i_a, i_b) AS SELECT a.i, b.i FROM base_a a, base_b b; + +--- missing some pkey columns: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx4 AS SELECT j FROM base_a; +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx5 AS SELECT a.i, b.j FROM base_a a, base_b b; + +--- with set-returning function: no index +CREATE INCREMENTAL MATERIALIZED VIEW mv_idx6 AS SELECT i FROM base_a, generate_series(1,10); + +ROLLBACK; + +-- type that doesn't have default operator class for access method btree +BEGIN; +CREATE TABLE table_json (j json); +CREATE INCREMENTAL MATERIALIZED VIEW mv_json AS SELECT * from table_json; +ROLLBACK; + +-- cleanup + +DROP TABLE rls_tbl CASCADE; +DROP TABLE num_tbl CASCADE; +DROP USER regress_ivm_user; +DROP USER regress_ivm_admin; + +DROP TABLE mv_base_b CASCADE; +DROP TABLE mv_base_a CASCADE; -- 2.43.0 --Multipart=_Fri__3_Jul_2026_19_11_16_+0900_CskxSIu_iGcDMEyM Content-Type: text/x-diff; name="v39-0006-Add-Incremental-View-Maintenance-support.patch" Content-Disposition: attachment; filename="v39-0006-Add-Incremental-View-Maintenance-support.patch" Content-Transfer-Encoding: 7bit ^ permalink raw reply [nested|flat] 78+ messages in thread
end of thread, other threads:[~2026-05-29 09:31 UTC | newest] Thread overview: 78+ messages (download: mbox mbox.gz follow: Atom feed) -- links below jump to the message on this page -- 2021-03-10 02:11 [PATCH v28 10/11] Add regression tests for Incremental View Maintenance Takuma Hoshiai <[email protected]> 2021-03-10 02:11 [PATCH v31 10/11] Add regression tests for Incremental View Maintenance Takuma Hoshiai <[email protected]> 2021-03-10 02:11 [PATCH v23 09/15] Add regression tests for Incremental View Maintenance Takuma Hoshiai <[email protected]> 2021-03-10 02:11 [PATCH v29 10/11] Add regression tests for Incremental View Maintenance Takuma Hoshiai <[email protected]> 2021-03-10 02:11 [PATCH v27 8/9] Add regression tests for Incremental View Maintenance Takuma Hoshiai <[email protected]> 2021-03-10 02:11 [PATCH v26 09/10] Add regression tests for Incremental View Maintenance Takuma Hoshiai <[email protected]> 2021-03-10 02:11 [PATCH v24 09/15] Add regression tests for Incremental View Maintenance Takuma Hoshiai <[email protected]> 2021-03-10 02:11 [PATCH v34 10/11] Add regression tests for Incremental View Maintenance Takuma Hoshiai <[email protected]> 2021-03-10 02:11 [PATCH v25 09/15] Add regression tests for Incremental View Maintenance Takuma Hoshiai <[email protected]> 2021-03-10 02:11 [PATCH v32 10/11] Add regression tests for Incremental View Maintenance Takuma Hoshiai <[email protected]> 2021-03-10 02:11 [PATCH v33 10/11] Add regression tests for Incremental View Maintenance Takuma Hoshiai <[email protected]> 2021-03-10 02:11 [PATCH v24 09/15] Add regression tests for Incremental View Maintenance Takuma Hoshiai <[email protected]> 2021-03-10 02:11 [PATCH v30 10/11] Add regression tests for Incremental View Maintenance Takuma Hoshiai <[email protected]> 2021-03-10 02:11 [PATCH v27 8/9] Add regression tests for Incremental View Maintenance Takuma Hoshiai <[email protected]> 2021-03-10 02:11 [PATCH v29 10/11] Add regression tests for Incremental View Maintenance Takuma Hoshiai <[email protected]> 2023-09-22 04:53 [PATCH v7 4/7] Row pattern recognition patch (executor). Tatsuo Ishii <[email protected]> 2026-05-29 09:31 [PATCH v37 10/11] Add regression tests for Incremental View Maintenance Yugo Nagata <[email protected]> 2026-05-29 09:31 [PATCH v39 7/8] Add regression tests for Incremental View Maintenance Yugo Nagata <[email protected]> 2026-05-29 09:31 [PATCH v39 7/8] Add regression tests for Incremental View Maintenance Yugo Nagata <[email protected]> 2026-05-29 09:31 [PATCH v38 10/11] Add regression tests for Incremental View Maintenance Yugo Nagata <[email protected]> 2026-05-29 09:31 [PATCH v38 10/11] Add regression tests for Incremental View Maintenance Yugo Nagata <[email protected]> 2026-05-29 09:31 [PATCH v39 7/8] Add regression tests for Incremental View Maintenance Yugo Nagata <[email protected]> 2026-05-29 09:31 [PATCH v38 10/11] Add regression tests for Incremental View Maintenance Yugo Nagata <[email protected]> 2026-05-29 09:31 [PATCH v39 7/8] Add regression tests for Incremental View Maintenance Yugo Nagata <[email protected]> 2026-05-29 09:31 [PATCH v37 10/11] Add regression tests for Incremental View Maintenance Yugo Nagata <[email protected]> 2026-05-29 09:31 [PATCH v39 7/8] Add regression tests for Incremental View Maintenance Yugo Nagata <[email protected]> 2026-05-29 09:31 [PATCH v37 10/11] Add regression tests for Incremental View Maintenance Yugo Nagata <[email protected]> 2026-05-29 09:31 [PATCH v38 10/11] Add regression tests for Incremental View Maintenance Yugo Nagata <[email protected]> 2026-05-29 09:31 [PATCH v37 10/11] Add regression tests for Incremental View Maintenance Yugo Nagata <[email protected]> 2026-05-29 09:31 [PATCH v37 10/11] Add regression tests for Incremental View Maintenance Yugo Nagata <[email protected]> 2026-05-29 09:31 [PATCH v37 10/11] Add regression tests for Incremental View Maintenance Yugo Nagata <[email protected]> 2026-05-29 09:31 [PATCH v38 10/11] Add regression tests for Incremental View Maintenance Yugo Nagata <[email protected]> 2026-05-29 09:31 [PATCH v38 10/11] Add regression tests for Incremental View Maintenance Yugo Nagata <[email protected]> 2026-05-29 09:31 [PATCH v38 10/11] Add regression tests for Incremental View Maintenance Yugo Nagata <[email protected]> 2026-05-29 09:31 [PATCH v39 7/8] Add regression tests for Incremental View Maintenance Yugo Nagata <[email protected]> 2026-05-29 09:31 [PATCH v38 10/11] Add regression tests for Incremental View Maintenance Yugo Nagata <[email protected]> 2026-05-29 09:31 [PATCH v37 10/11] Add regression tests for Incremental View Maintenance Yugo Nagata <[email protected]> 2026-05-29 09:31 [PATCH v37 10/11] Add regression tests for Incremental View Maintenance Yugo Nagata <[email protected]> 2026-05-29 09:31 [PATCH v38 10/11] Add regression tests for Incremental View Maintenance Yugo Nagata <[email protected]> 2026-05-29 09:31 [PATCH v39 7/8] Add regression tests for Incremental View Maintenance Yugo Nagata <[email protected]> 2026-05-29 09:31 [PATCH v39 7/8] Add regression tests for Incremental View Maintenance Yugo Nagata <[email protected]> 2026-05-29 09:31 [PATCH v38 10/11] Add regression tests for Incremental View Maintenance Yugo Nagata <[email protected]> 2026-05-29 09:31 [PATCH v37 10/11] Add regression tests for Incremental View Maintenance Yugo Nagata <[email protected]> 2026-05-29 09:31 [PATCH v37 10/11] Add regression tests for Incremental View Maintenance Yugo Nagata <[email protected]> 2026-05-29 09:31 [PATCH v37 10/11] Add regression tests for Incremental View Maintenance Yugo Nagata <[email protected]> 2026-05-29 09:31 [PATCH v38 10/11] Add regression tests for Incremental View Maintenance Yugo Nagata <[email protected]> 2026-05-29 09:31 [PATCH v39 7/8] Add regression tests for Incremental View Maintenance Yugo Nagata <[email protected]> 2026-05-29 09:31 [PATCH v39 7/8] Add regression tests for Incremental View Maintenance Yugo Nagata <[email protected]> 2026-05-29 09:31 [PATCH v37 10/11] Add regression tests for Incremental View Maintenance Yugo Nagata <[email protected]> 2026-05-29 09:31 [PATCH v39 7/8] Add regression tests for Incremental View Maintenance Yugo Nagata <[email protected]> 2026-05-29 09:31 [PATCH v39 7/8] Add regression tests for Incremental View Maintenance Yugo Nagata <[email protected]> 2026-05-29 09:31 [PATCH v38 10/11] Add regression tests for Incremental View Maintenance Yugo Nagata <[email protected]> 2026-05-29 09:31 [PATCH v37 10/11] Add regression tests for Incremental View Maintenance Yugo Nagata <[email protected]> 2026-05-29 09:31 [PATCH v37 10/11] Add regression tests for Incremental View Maintenance Yugo Nagata <[email protected]> 2026-05-29 09:31 [PATCH v39 7/8] Add regression tests for Incremental View Maintenance Yugo Nagata <[email protected]> 2026-05-29 09:31 [PATCH v39 7/8] Add regression tests for Incremental View Maintenance Yugo Nagata <[email protected]> 2026-05-29 09:31 [PATCH v37 10/11] Add regression tests for Incremental View Maintenance Yugo Nagata <[email protected]> 2026-05-29 09:31 [PATCH v37 10/11] Add regression tests for Incremental View Maintenance Yugo Nagata <[email protected]> 2026-05-29 09:31 [PATCH v37 10/11] Add regression tests for Incremental View Maintenance Yugo Nagata <[email protected]> 2026-05-29 09:31 [PATCH v38 10/11] Add regression tests for Incremental View Maintenance Yugo Nagata <[email protected]> 2026-05-29 09:31 [PATCH v37 10/11] Add regression tests for Incremental View Maintenance Yugo Nagata <[email protected]> 2026-05-29 09:31 [PATCH v38 10/11] Add regression tests for Incremental View Maintenance Yugo Nagata <[email protected]> 2026-05-29 09:31 [PATCH v39 7/8] Add regression tests for Incremental View Maintenance Yugo Nagata <[email protected]> 2026-05-29 09:31 [PATCH v37 10/11] Add regression tests for Incremental View Maintenance Yugo Nagata <[email protected]> 2026-05-29 09:31 [PATCH v38 10/11] Add regression tests for Incremental View Maintenance Yugo Nagata <[email protected]> 2026-05-29 09:31 [PATCH v37 10/11] Add regression tests for Incremental View Maintenance Yugo Nagata <[email protected]> 2026-05-29 09:31 [PATCH v39 7/8] Add regression tests for Incremental View Maintenance Yugo Nagata <[email protected]> 2026-05-29 09:31 [PATCH v38 10/11] Add regression tests for Incremental View Maintenance Yugo Nagata <[email protected]> 2026-05-29 09:31 [PATCH v39 7/8] Add regression tests for Incremental View Maintenance Yugo Nagata <[email protected]> 2026-05-29 09:31 [PATCH v38 10/11] Add regression tests for Incremental View Maintenance Yugo Nagata <[email protected]> 2026-05-29 09:31 [PATCH v38 10/11] Add regression tests for Incremental View Maintenance Yugo Nagata <[email protected]> 2026-05-29 09:31 [PATCH v37 10/11] Add regression tests for Incremental View Maintenance Yugo Nagata <[email protected]> 2026-05-29 09:31 [PATCH v38 10/11] Add regression tests for Incremental View Maintenance Yugo Nagata <[email protected]> 2026-05-29 09:31 [PATCH v39 7/8] Add regression tests for Incremental View Maintenance Yugo Nagata <[email protected]> 2026-05-29 09:31 [PATCH v39 7/8] Add regression tests for Incremental View Maintenance Yugo Nagata <[email protected]> 2026-05-29 09:31 [PATCH v38 10/11] Add regression tests for Incremental View Maintenance Yugo Nagata <[email protected]> 2026-05-29 09:31 [PATCH v38 10/11] Add regression tests for Incremental View Maintenance Yugo Nagata <[email protected]> 2026-05-29 09:31 [PATCH v39 7/8] Add regression tests for Incremental View Maintenance Yugo Nagata <[email protected]>
This inbox is served by agora; see mirroring instructions for how to clone and mirror all data and code used for this inbox