Building PostgreSQL with -DENFORCE_REGRESSION_TEST_NAME_RESTRICTIONS causes the regression tests of pg_ivm to fail, because the role names used in the tests are not compliant with what upstream expects. Enforcing restrictions in the regression tests is a good practice to have, as roles are shared objects and running the tests could manipulate existing clusters in unwanted ways.
1745 lines
63 KiB
Text
1745 lines
63 KiB
Text
CREATE EXTENSION pg_ivm;
|
|
GRANT ALL ON SCHEMA public TO public;
|
|
-- 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);
|
|
SELECT pgivm.create_immv('mv_ivm_1', 'SELECT i,j,k FROM mv_base_a a INNER JOIN mv_base_b b USING(i)');
|
|
NOTICE: could not create an index on immv "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 immv for efficient incremental maintenance.
|
|
create_immv
|
|
-------------
|
|
4
|
|
(1 row)
|
|
|
|
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)
|
|
|
|
-- 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;
|
|
SELECT pgivm.create_immv('mv_ivm_func', 'SELECT * FROM ivm_func()');
|
|
NOTICE: could not create an index on immv "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 immv for efficient incremental maintenance.
|
|
create_immv
|
|
-------------
|
|
1
|
|
(1 row)
|
|
|
|
SELECT pgivm.create_immv('mv_ivm_no_tbl', 'SELECT 1');
|
|
NOTICE: could not create an index on immv "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 immv for efficient incremental maintenance.
|
|
create_immv
|
|
-------------
|
|
1
|
|
(1 row)
|
|
|
|
ROLLBACK;
|
|
-- result of materialized view have DISTINCT clause or the duplicate result.
|
|
BEGIN;
|
|
SELECT pgivm.create_immv('mv_ivm_duplicate', 'SELECT j FROM mv_base_a');
|
|
NOTICE: could not create an index on immv "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 immv for efficient incremental maintenance.
|
|
create_immv
|
|
-------------
|
|
5
|
|
(1 row)
|
|
|
|
SELECT pgivm.create_immv('mv_ivm_distinct', 'SELECT DISTINCT j FROM mv_base_a');
|
|
NOTICE: created index "mv_ivm_distinct_index" on immv "mv_ivm_distinct"
|
|
create_immv
|
|
-------------
|
|
5
|
|
(1 row)
|
|
|
|
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 | __ivm_count__
|
|
----+---------------
|
|
10 | 1
|
|
20 | 2
|
|
30 | 1
|
|
40 | 1
|
|
50 | 1
|
|
(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 | __ivm_count__
|
|
----+---------------
|
|
10 | 1
|
|
20 | 1
|
|
30 | 1
|
|
40 | 1
|
|
50 | 1
|
|
(5 rows)
|
|
|
|
ROLLBACK;
|
|
-- support SUM(), COUNT() and AVG() aggregate functions
|
|
BEGIN;
|
|
SELECT pgivm.create_immv('mv_ivm_agg', 'SELECT i, SUM(j), COUNT(i), AVG(j) FROM mv_base_a GROUP BY i');
|
|
NOTICE: created index "mv_ivm_agg_index" on immv "mv_ivm_agg"
|
|
create_immv
|
|
-------------
|
|
5
|
|
(1 row)
|
|
|
|
SELECT * FROM mv_ivm_agg ORDER BY 1,2,3,4;
|
|
i | sum | count | avg | __ivm_count_sum__ | __ivm_count_avg__ | __ivm_sum_avg__ | __ivm_count__
|
|
---+-----+-------+---------------------+-------------------+-------------------+-----------------+---------------
|
|
1 | 10 | 1 | 10.0000000000000000 | 1 | 1 | 10 | 1
|
|
2 | 20 | 1 | 20.0000000000000000 | 1 | 1 | 20 | 1
|
|
3 | 30 | 1 | 30.0000000000000000 | 1 | 1 | 30 | 1
|
|
4 | 40 | 1 | 40.0000000000000000 | 1 | 1 | 40 | 1
|
|
5 | 50 | 1 | 50.0000000000000000 | 1 | 1 | 50 | 1
|
|
(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 | __ivm_count_sum__ | __ivm_count_avg__ | __ivm_sum_avg__ | __ivm_count__
|
|
---+-----+-------+---------------------+-------------------+-------------------+-----------------+---------------
|
|
1 | 10 | 1 | 10.0000000000000000 | 1 | 1 | 10 | 1
|
|
2 | 120 | 2 | 60.0000000000000000 | 2 | 2 | 120 | 2
|
|
3 | 30 | 1 | 30.0000000000000000 | 1 | 1 | 30 | 1
|
|
4 | 40 | 1 | 40.0000000000000000 | 1 | 1 | 40 | 1
|
|
5 | 50 | 1 | 50.0000000000000000 | 1 | 1 | 50 | 1
|
|
(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 | __ivm_count_sum__ | __ivm_count_avg__ | __ivm_sum_avg__ | __ivm_count__
|
|
---+-----+-------+----------------------+-------------------+-------------------+-----------------+---------------
|
|
1 | 10 | 1 | 10.0000000000000000 | 1 | 1 | 10 | 1
|
|
2 | 220 | 2 | 110.0000000000000000 | 2 | 2 | 220 | 2
|
|
3 | 30 | 1 | 30.0000000000000000 | 1 | 1 | 30 | 1
|
|
4 | 40 | 1 | 40.0000000000000000 | 1 | 1 | 40 | 1
|
|
5 | 50 | 1 | 50.0000000000000000 | 1 | 1 | 50 | 1
|
|
(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 | __ivm_count_sum__ | __ivm_count_avg__ | __ivm_sum_avg__ | __ivm_count__
|
|
---+-----+-------+---------------------+-------------------+-------------------+-----------------+---------------
|
|
1 | 10 | 1 | 10.0000000000000000 | 1 | 1 | 10 | 1
|
|
2 | 20 | 1 | 20.0000000000000000 | 1 | 1 | 20 | 1
|
|
3 | 30 | 1 | 30.0000000000000000 | 1 | 1 | 30 | 1
|
|
4 | 40 | 1 | 40.0000000000000000 | 1 | 1 | 40 | 1
|
|
5 | 50 | 1 | 50.0000000000000000 | 1 | 1 | 50 | 1
|
|
(5 rows)
|
|
|
|
ROLLBACK;
|
|
-- support COUNT(*) aggregate function
|
|
BEGIN;
|
|
SELECT pgivm.create_immv('mv_ivm_agg', 'SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i');
|
|
NOTICE: created index "mv_ivm_agg_index" on immv "mv_ivm_agg"
|
|
create_immv
|
|
-------------
|
|
5
|
|
(1 row)
|
|
|
|
SELECT * FROM mv_ivm_agg ORDER BY 1,2,3;
|
|
i | sum | count | __ivm_count_sum__ | __ivm_count__
|
|
---+-----+-------+-------------------+---------------
|
|
1 | 10 | 1 | 1 | 1
|
|
2 | 20 | 1 | 1 | 1
|
|
3 | 30 | 1 | 1 | 1
|
|
4 | 40 | 1 | 1 | 1
|
|
5 | 50 | 1 | 1 | 1
|
|
(5 rows)
|
|
|
|
INSERT INTO mv_base_a VALUES(2,100);
|
|
SELECT * FROM mv_ivm_agg ORDER BY 1,2,3;
|
|
i | sum | count | __ivm_count_sum__ | __ivm_count__
|
|
---+-----+-------+-------------------+---------------
|
|
1 | 10 | 1 | 1 | 1
|
|
2 | 120 | 2 | 2 | 2
|
|
3 | 30 | 1 | 1 | 1
|
|
4 | 40 | 1 | 1 | 1
|
|
5 | 50 | 1 | 1 | 1
|
|
(5 rows)
|
|
|
|
ROLLBACK;
|
|
-- TRUNCATE a base table in aggregate views
|
|
BEGIN;
|
|
SELECT pgivm.create_immv('mv_ivm_agg', 'SELECT i, SUM(j), COUNT(*) FROM mv_base_a GROUP BY i');
|
|
NOTICE: created index "mv_ivm_agg_index" on immv "mv_ivm_agg"
|
|
create_immv
|
|
-------------
|
|
5
|
|
(1 row)
|
|
|
|
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;
|
|
SELECT pgivm.create_immv('mv_ivm_group', 'SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a');
|
|
create_immv
|
|
-------------
|
|
1
|
|
(1 row)
|
|
|
|
SELECT * FROM mv_ivm_group ORDER BY 1;
|
|
sum | count | avg | __ivm_count_sum__ | __ivm_count_avg__ | __ivm_sum_avg__ | __ivm_count__
|
|
-----+-------+---------------------+-------------------+-------------------+-----------------+---------------
|
|
150 | 5 | 30.0000000000000000 | 5 | 5 | 150 | 5
|
|
(1 row)
|
|
|
|
INSERT INTO mv_base_a VALUES(6,60);
|
|
SELECT * FROM mv_ivm_group ORDER BY 1;
|
|
sum | count | avg | __ivm_count_sum__ | __ivm_count_avg__ | __ivm_sum_avg__ | __ivm_count__
|
|
-----+-------+---------------------+-------------------+-------------------+-----------------+---------------
|
|
210 | 6 | 35.0000000000000000 | 6 | 6 | 210 | 6
|
|
(1 row)
|
|
|
|
DELETE FROM mv_base_a;
|
|
SELECT * FROM mv_ivm_group ORDER BY 1;
|
|
sum | count | avg | __ivm_count_sum__ | __ivm_count_avg__ | __ivm_sum_avg__ | __ivm_count__
|
|
-----+-------+-----+-------------------+-------------------+-----------------+---------------
|
|
| 0 | | 0 | 0 | | 0
|
|
(1 row)
|
|
|
|
ROLLBACK;
|
|
-- TRUNCATE a base table in aggregate views without GROUP clause
|
|
BEGIN;
|
|
SELECT pgivm.create_immv('mv_ivm_group', 'SELECT SUM(j), COUNT(j), AVG(j) FROM mv_base_a');
|
|
create_immv
|
|
-------------
|
|
1
|
|
(1 row)
|
|
|
|
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;
|
|
SELECT pgivm.create_immv('mv_ivm_avg_bug', 'SELECT i, SUM(j), COUNT(j), AVG(j) FROM mv_base_A GROUP BY i');
|
|
NOTICE: created index "mv_ivm_avg_bug_index" on immv "mv_ivm_avg_bug"
|
|
create_immv
|
|
-------------
|
|
5
|
|
(1 row)
|
|
|
|
SELECT * FROM mv_ivm_avg_bug ORDER BY 1,2,3;
|
|
i | sum | count | avg | __ivm_count_sum__ | __ivm_count_avg__ | __ivm_sum_avg__ | __ivm_count__
|
|
---+-----+-------+---------------------+-------------------+-------------------+-----------------+---------------
|
|
1 | 10 | 1 | 10.0000000000000000 | 1 | 1 | 10 | 1
|
|
2 | 20 | 1 | 20.0000000000000000 | 1 | 1 | 20 | 1
|
|
3 | 30 | 1 | 30.0000000000000000 | 1 | 1 | 30 | 1
|
|
4 | 40 | 1 | 40.0000000000000000 | 1 | 1 | 40 | 1
|
|
5 | 50 | 1 | 50.0000000000000000 | 1 | 1 | 50 | 1
|
|
(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 | __ivm_count_sum__ | __ivm_count_avg__ | __ivm_sum_avg__ | __ivm_count__
|
|
---+-----+-------+---------------------+-------------------+-------------------+-----------------+---------------
|
|
1 | 10 | 3 | 3.3333333333333333 | 3 | 3 | 10 | 3
|
|
2 | 80 | 3 | 26.6666666666666667 | 3 | 3 | 80 | 3
|
|
3 | 30 | 1 | 30.0000000000000000 | 1 | 1 | 30 | 1
|
|
4 | 40 | 1 | 40.0000000000000000 | 1 | 1 | 40 | 1
|
|
5 | 50 | 1 | 50.0000000000000000 | 1 | 1 | 50 | 1
|
|
(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 | __ivm_count_sum__ | __ivm_count_avg__ | __ivm_sum_avg__ | __ivm_count__
|
|
---+-----+-------+---------------------+-------------------+-------------------+-----------------+---------------
|
|
1 | 10 | 1 | 10.0000000000000000 | 1 | 1 | 10 | 1
|
|
2 | 20 | 1 | 20.0000000000000000 | 1 | 1 | 20 | 1
|
|
3 | 30 | 1 | 30.0000000000000000 | 1 | 1 | 30 | 1
|
|
4 | 40 | 1 | 40.0000000000000000 | 1 | 1 | 40 | 1
|
|
5 | 50 | 1 | 50.0000000000000000 | 1 | 1 | 50 | 1
|
|
(5 rows)
|
|
|
|
ROLLBACK;
|
|
-- support MIN(), MAX() aggregate functions
|
|
BEGIN;
|
|
SELECT pgivm.create_immv('mv_ivm_min_max(i, min_j, max_j)', 'SELECT i, MIN(j), MAX(j) FROM mv_base_a GROUP BY i');
|
|
NOTICE: created index "mv_ivm_min_max_index" on immv "mv_ivm_min_max"
|
|
create_immv
|
|
-------------
|
|
5
|
|
(1 row)
|
|
|
|
SELECT * FROM mv_ivm_min_max ORDER BY 1,2,3;
|
|
i | min_j | max_j | __ivm_count_min_j__ | __ivm_count_max_j__ | __ivm_count__
|
|
---+-------+-------+---------------------+---------------------+---------------
|
|
1 | 10 | 10 | 1 | 1 | 1
|
|
2 | 20 | 20 | 1 | 1 | 1
|
|
3 | 30 | 30 | 1 | 1 | 1
|
|
4 | 40 | 40 | 1 | 1 | 1
|
|
5 | 50 | 50 | 1 | 1 | 1
|
|
(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_j | max_j | __ivm_count_min_j__ | __ivm_count_max_j__ | __ivm_count__
|
|
---+-------+-------+---------------------+---------------------+---------------
|
|
1 | 10 | 12 | 3 | 3 | 3
|
|
2 | 20 | 22 | 3 | 3 | 3
|
|
3 | 30 | 32 | 3 | 3 | 3
|
|
4 | 40 | 42 | 3 | 3 | 3
|
|
5 | 50 | 52 | 3 | 3 | 3
|
|
(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_j | max_j | __ivm_count_min_j__ | __ivm_count_max_j__ | __ivm_count__
|
|
---+-------+-------+---------------------+---------------------+---------------
|
|
1 | 11 | 12 | 2 | 2 | 2
|
|
2 | 20 | 22 | 2 | 2 | 2
|
|
3 | 30 | 31 | 2 | 2 | 2
|
|
4 | 40 | 42 | 3 | 3 | 3
|
|
5 | 50 | 52 | 3 | 3 | 3
|
|
(5 rows)
|
|
|
|
ROLLBACK;
|
|
-- support MIN(), MAX() aggregate functions without GROUP clause
|
|
BEGIN;
|
|
SELECT pgivm.create_immv('mv_ivm_min_max(min_j, max_j)', 'SELECT MIN(j), MAX(j) FROM mv_base_a');
|
|
create_immv
|
|
-------------
|
|
1
|
|
(1 row)
|
|
|
|
SELECT * FROM mv_ivm_min_max;
|
|
min_j | max_j | __ivm_count_min_j__ | __ivm_count_max_j__ | __ivm_count__
|
|
-------+-------+---------------------+---------------------+---------------
|
|
10 | 50 | 5 | 5 | 5
|
|
(1 row)
|
|
|
|
INSERT INTO mv_base_a VALUES
|
|
(0,0), (6,60), (7,70);
|
|
SELECT * FROM mv_ivm_min_max;
|
|
min_j | max_j | __ivm_count_min_j__ | __ivm_count_max_j__ | __ivm_count__
|
|
-------+-------+---------------------+---------------------+---------------
|
|
0 | 70 | 8 | 8 | 8
|
|
(1 row)
|
|
|
|
DELETE FROM mv_base_a WHERE (i,j) IN ((0,0), (7,70));
|
|
SELECT * FROM mv_ivm_min_max;
|
|
min_j | max_j | __ivm_count_min_j__ | __ivm_count_max_j__ | __ivm_count__
|
|
-------+-------+---------------------+---------------------+---------------
|
|
10 | 60 | 6 | 6 | 6
|
|
(1 row)
|
|
|
|
DELETE FROM mv_base_a;
|
|
SELECT * FROM mv_ivm_min_max;
|
|
min_j | max_j | __ivm_count_min_j__ | __ivm_count_max_j__ | __ivm_count__
|
|
-------+-------+---------------------+---------------------+---------------
|
|
| | 0 | 0 | 0
|
|
(1 row)
|
|
|
|
ROLLBACK;
|
|
-- Test MIN/MAX after search_path change
|
|
BEGIN;
|
|
SELECT pgivm.create_immv('mv_ivm_min', 'SELECT MIN(j) FROM mv_base_a');
|
|
create_immv
|
|
-------------
|
|
1
|
|
(1 row)
|
|
|
|
SELECT * FROM mv_ivm_min ORDER BY 1,2,3;
|
|
min | __ivm_count_min__ | __ivm_count__
|
|
-----+-------------------+---------------
|
|
10 | 5 | 5
|
|
(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 ORDER BY 1,2,3;
|
|
min | __ivm_count_min__ | __ivm_count__
|
|
-----+-------------------+---------------
|
|
20 | 4 | 4
|
|
(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 ORDER BY 1,2,3;
|
|
min | __ivm_count_min__ | __ivm_count__
|
|
-----+-------------------+---------------
|
|
30 | 3 | 3
|
|
(1 row)
|
|
|
|
ROLLBACK;
|
|
-- aggregate views with column names specified
|
|
BEGIN;
|
|
SELECT pgivm.create_immv('mv_ivm_agg(a)', 'SELECT i, SUM(j) FROM mv_base_a GROUP BY i');
|
|
NOTICE: created index "mv_ivm_agg_index" on immv "mv_ivm_agg"
|
|
create_immv
|
|
-------------
|
|
5
|
|
(1 row)
|
|
|
|
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 | __ivm_count_sum__ | __ivm_count__
|
|
---+------+-------------------+---------------
|
|
1 | 110 | 2 | 2
|
|
2 | 2200 | 2 | 2
|
|
3 | 300 | 1 | 1
|
|
4 | 40 | 1 | 1
|
|
5 | 50 | 1 | 1
|
|
(5 rows)
|
|
|
|
ROLLBACK;
|
|
BEGIN;
|
|
SELECT pgivm.create_immv('mv_ivm_agg(a,b)', 'SELECT i, SUM(j) FROM mv_base_a GROUP BY i');
|
|
NOTICE: created index "mv_ivm_agg_index" on immv "mv_ivm_agg"
|
|
create_immv
|
|
-------------
|
|
5
|
|
(1 row)
|
|
|
|
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 | __ivm_count_b__ | __ivm_count__
|
|
---+------+-----------------+---------------
|
|
1 | 110 | 2 | 2
|
|
2 | 2200 | 2 | 2
|
|
3 | 300 | 1 | 1
|
|
4 | 40 | 1 | 1
|
|
5 | 50 | 1 | 1
|
|
(5 rows)
|
|
|
|
ROLLBACK;
|
|
BEGIN;
|
|
SELECT pgivm.create_immv('mv_ivm_agg(a,b,c)', '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);
|
|
SELECT pgivm.create_immv('mv_self(v1, v2)',
|
|
'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 immv "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 immv for efficient incremental maintenance.
|
|
create_immv
|
|
-------------
|
|
3
|
|
(1 row)
|
|
|
|
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);
|
|
SELECT pgivm.create_immv('mv(v1, v2)', 'SELECT r.v, s.v FROM base_r AS r JOIN base_s AS s USING(i)');;
|
|
NOTICE: could not create an index on immv "mv" automatically
|
|
DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause.
|
|
HINT: Create an index on the immv for efficient incremental maintenance.
|
|
create_immv
|
|
-------------
|
|
3
|
|
(1 row)
|
|
|
|
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)
|
|
|
|
-- support foreign reference constraints
|
|
BEGIN;
|
|
WARNING: there is already a transaction in progress
|
|
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);
|
|
SELECT pgivm.create_immv('mv_ri(i1, i2)', 'SELECT ri1.i, ri2.i FROM ri1 JOIN ri2 USING(i)');
|
|
NOTICE: created index "mv_ri_index" on immv "mv_ri"
|
|
create_immv
|
|
-------------
|
|
3
|
|
(1 row)
|
|
|
|
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;
|
|
-- support subquery for using EXISTS()
|
|
BEGIN;
|
|
SELECT pgivm.create_immv('mv_ivm_exists_subquery', 'SELECT a.i, a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i)');
|
|
NOTICE: could not create an index on immv "mv_ivm_exists_subquery" automatically
|
|
DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause.
|
|
HINT: Create an index on the immv for efficient incremental maintenance.
|
|
create_immv
|
|
-------------
|
|
4
|
|
(1 row)
|
|
|
|
SELECT pgivm.create_immv('mv_ivm_exists_subquery2', 'SELECT a.i,a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) AND a.i > 2');
|
|
NOTICE: could not create an index on immv "mv_ivm_exists_subquery2" automatically
|
|
DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause.
|
|
HINT: Create an index on the immv for efficient incremental maintenance.
|
|
create_immv
|
|
-------------
|
|
2
|
|
(1 row)
|
|
|
|
SELECT * FROM mv_ivm_exists_subquery ORDER BY i, j;
|
|
i | j | __ivm_exists_count_0__
|
|
---+----+------------------------
|
|
1 | 10 | 1
|
|
2 | 20 | 1
|
|
3 | 30 | 1
|
|
4 | 40 | 1
|
|
(4 rows)
|
|
|
|
SELECT * FROM mv_ivm_exists_subquery2 ORDER BY i, j;
|
|
i | j | __ivm_exists_count_0__
|
|
---+----+------------------------
|
|
3 | 30 | 1
|
|
4 | 40 | 1
|
|
(2 rows)
|
|
|
|
INSERT INTO mv_base_a VALUES(1,10),(6,60),(3,30),(3,300);
|
|
SELECT * FROM mv_ivm_exists_subquery ORDER BY i, j;
|
|
i | j | __ivm_exists_count_0__
|
|
---+-----+------------------------
|
|
1 | 10 | 1
|
|
1 | 10 | 1
|
|
2 | 20 | 1
|
|
3 | 30 | 1
|
|
3 | 30 | 1
|
|
3 | 300 | 1
|
|
4 | 40 | 1
|
|
(7 rows)
|
|
|
|
SELECT * FROM mv_ivm_exists_subquery2 ORDER BY i, j;
|
|
i | j | __ivm_exists_count_0__
|
|
---+-----+------------------------
|
|
3 | 30 | 1
|
|
3 | 30 | 1
|
|
3 | 300 | 1
|
|
4 | 40 | 1
|
|
(4 rows)
|
|
|
|
INSERT INTO mv_base_b VALUES(1,101);
|
|
INSERT INTO mv_base_b VALUES(1,111);
|
|
INSERT INTO mv_base_b VALUES(2,102);
|
|
INSERT INTO mv_base_b VALUES(6,106);
|
|
SELECT * FROM mv_ivm_exists_subquery ORDER BY i, j;
|
|
i | j | __ivm_exists_count_0__
|
|
---+-----+------------------------
|
|
1 | 10 | 3
|
|
1 | 10 | 3
|
|
2 | 20 | 2
|
|
3 | 30 | 1
|
|
3 | 30 | 1
|
|
3 | 300 | 1
|
|
4 | 40 | 1
|
|
6 | 60 | 1
|
|
(8 rows)
|
|
|
|
SELECT * FROM mv_ivm_exists_subquery2 ORDER BY i, j;
|
|
i | j | __ivm_exists_count_0__
|
|
---+-----+------------------------
|
|
3 | 30 | 1
|
|
3 | 30 | 1
|
|
3 | 300 | 1
|
|
4 | 40 | 1
|
|
6 | 60 | 1
|
|
(5 rows)
|
|
|
|
UPDATE mv_base_a SET i = 1 WHERE j =60;
|
|
UPDATE mv_base_b SET i = 10 WHERE k = 101;
|
|
UPDATE mv_base_b SET k = 1002 WHERE k = 102;
|
|
SELECT * FROM mv_ivm_exists_subquery ORDER BY i, j;
|
|
i | j | __ivm_exists_count_0__
|
|
---+-----+------------------------
|
|
1 | 10 | 1
|
|
1 | 10 | 1
|
|
1 | 60 | 1
|
|
2 | 20 | 2
|
|
3 | 30 | 1
|
|
3 | 30 | 1
|
|
3 | 300 | 1
|
|
4 | 40 | 1
|
|
(8 rows)
|
|
|
|
SELECT * FROM mv_ivm_exists_subquery2 ORDER BY i, j;
|
|
i | j | __ivm_exists_count_0__
|
|
---+-----+------------------------
|
|
3 | 30 | 1
|
|
3 | 30 | 1
|
|
3 | 300 | 1
|
|
4 | 40 | 1
|
|
(4 rows)
|
|
|
|
DELETE FROM mv_base_a WHERE (i,j) = (1,60);
|
|
DELETE FROM mv_base_b WHERE i = 2;
|
|
SELECT * FROM mv_ivm_exists_subquery ORDER BY i, j;
|
|
i | j | __ivm_exists_count_0__
|
|
---+-----+------------------------
|
|
1 | 10 | 1
|
|
1 | 10 | 1
|
|
3 | 30 | 1
|
|
3 | 30 | 1
|
|
3 | 300 | 1
|
|
4 | 40 | 1
|
|
(6 rows)
|
|
|
|
SELECT * FROM mv_ivm_exists_subquery2 ORDER BY i, j;
|
|
i | j | __ivm_exists_count_0__
|
|
---+-----+------------------------
|
|
3 | 30 | 1
|
|
3 | 30 | 1
|
|
3 | 300 | 1
|
|
4 | 40 | 1
|
|
(4 rows)
|
|
|
|
--- EXISTS subquery with tuple duplication and DISTINCT
|
|
SELECT pgivm.create_immv('mv_ivm_exists_subquery_distinct', 'SELECT DISTINCT a.i, a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i)');
|
|
NOTICE: created index "mv_ivm_exists_subquery_distinct_index" on immv "mv_ivm_exists_subquery_distinct"
|
|
create_immv
|
|
-------------
|
|
4
|
|
(1 row)
|
|
|
|
DELETE FROM mv_base_b WHERE i = 1 or i = 3;
|
|
INSERT INTO mv_base_b VALUES (1,100), (3,300);
|
|
SELECT * FROM mv_ivm_exists_subquery ORDER BY i, j;
|
|
i | j | __ivm_exists_count_0__
|
|
---+-----+------------------------
|
|
1 | 10 | 1
|
|
1 | 10 | 1
|
|
3 | 30 | 1
|
|
3 | 30 | 1
|
|
3 | 300 | 1
|
|
4 | 40 | 1
|
|
(6 rows)
|
|
|
|
SELECT * FROM mv_ivm_exists_subquery_distinct ORDER BY i, j;
|
|
i | j | __ivm_exists_count_0__ | __ivm_count__
|
|
---+-----+------------------------+---------------
|
|
1 | 10 | 1 | 2
|
|
3 | 30 | 1 | 2
|
|
3 | 300 | 1 | 1
|
|
4 | 40 | 1 | 1
|
|
(4 rows)
|
|
|
|
ROLLBACK;
|
|
-- support simple subquery in FROM clause
|
|
BEGIN;
|
|
SELECT pgivm.create_immv('mv_ivm_subquery', 'SELECT a.i,a.j FROM mv_base_a a,( SELECT * FROM mv_base_b) b WHERE a.i = b.i');
|
|
NOTICE: could not create an index on immv "mv_ivm_subquery" automatically
|
|
DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause.
|
|
HINT: Create an index on the immv for efficient incremental maintenance.
|
|
create_immv
|
|
-------------
|
|
4
|
|
(1 row)
|
|
|
|
INSERT INTO mv_base_a VALUES(2,20);
|
|
INSERT INTO mv_base_b VALUES(3,300);
|
|
SELECT * FROM mv_ivm_subquery ORDER BY i,j;
|
|
i | j
|
|
---+----
|
|
1 | 10
|
|
2 | 20
|
|
2 | 20
|
|
3 | 30
|
|
3 | 30
|
|
4 | 40
|
|
(6 rows)
|
|
|
|
ROLLBACK;
|
|
-- disallow non-simple subqueries
|
|
SELECT pgivm.create_immv('mv_ivm_subquery', '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: aggregate functions in nested query are not supported on incrementally maintainable materialized view
|
|
SELECT pgivm.create_immv('mv_ivm_subquery', 'SELECT a.i,a.j FROM mv_base_a a, (SELECT DISTINCT i FROM mv_base_b) b WHERE a.i = b.i');
|
|
ERROR: DISTINCT clause in nested query are not supported on incrementally maintainable materialized view
|
|
SELECT pgivm.create_immv('mv_ivm_subquery', 'SELECT i,j FROM mv_base_a WHERE i IN (SELECT i FROM mv_base_b WHERE k < 103 )');
|
|
ERROR: this query is not allowed on incrementally maintainable materialized view
|
|
HINT: sublink only supports subquery with EXISTS clause in WHERE clause
|
|
SELECT pgivm.create_immv('mv_ivm_subquery', 'SELECT i,j, (SELECT k FROM mv_base_b LIMIT 1) FROM mv_base_a a');
|
|
ERROR: this query is not allowed on incrementally maintainable materialized view
|
|
HINT: sublink only supports subquery with EXISTS clause in WHERE clause
|
|
SELECT pgivm.create_immv('mv_ivm_subquery', 'SELECT i,j, (SELECT k FROM mv_base_b LIMIT 1) + 1 FROM mv_base_a a');
|
|
ERROR: this query is not allowed on incrementally maintainable materialized view
|
|
HINT: sublink only supports subquery with EXISTS clause in WHERE clause
|
|
SELECT pgivm.create_immv('mv_ivm_subquery', 'SELECT * FROM generate_series(1, (SELECT k FROM mv_base_b LIMIT 1)) AS v');
|
|
ERROR: this query is not allowed on incrementally maintainable materialized view
|
|
HINT: sublink only supports subquery with EXISTS clause in WHERE clause
|
|
SELECT pgivm.create_immv('mv_ivm_subquery', 'SELECT a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i)');
|
|
ERROR: this query is not allowed on incrementally maintainable materialized view
|
|
HINT: targetlist must contain vars that are referred to in EXISTS subquery
|
|
SELECT pgivm.create_immv('mv_ivm_subquery', '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 > 2');
|
|
ERROR: this query is not allowed on incrementally maintainable materialized view
|
|
HINT: OR or NOT conditions and EXISTS condition can not be used together
|
|
SELECT pgivm.create_immv('mv_ivm_subquery', 'SELECT a.j FROM mv_base_a a WHERE EXISTS(SELECT 1 FROM mv_base_a a2 WHERE EXISTS(SELECT 1 FROM mv_base_b b WHERE a2.i = b.i))');
|
|
ERROR: nested sublink is not supported on incrementally maintainable materialized view
|
|
SELECT pgivm.create_immv('mv_ivm_subquery', 'SELECT EXISTS(SELECT 1 from mv_base_b) FROM mv_base_a a');
|
|
ERROR: this query is not allowed on incrementally maintainable materialized view
|
|
HINT: sublink only supports subquery with EXISTS clause in WHERE clause
|
|
SELECT pgivm.create_immv('mv_ivm_subquery', 'SELECT false OR EXISTS(SELECT 1 FROM mv_base_a) FROM mv_base_b');
|
|
ERROR: this query is not allowed on incrementally maintainable materialized view
|
|
HINT: OR or NOT conditions and EXISTS condition can not be used together
|
|
SELECT pgivm.create_immv('mv_ivm_subquery', 'SELECT * FROM generate_series(1, CASE EXISTS(SELECT 1 FROM mv_base_a) WHEN true THEN 100 ELSE 10 END), mv_base_b');
|
|
ERROR: this query is not allowed on incrementally maintainable materialized view
|
|
HINT: sublink only supports subquery with EXISTS clause in WHERE clause
|
|
SELECT pgivm.create_immv('mv_ivm_subquery', 'SELECT * FROM mv_base_a a WHERE CASE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) WHEN true THEN false ELSE true END');
|
|
ERROR: this query is not allowed on incrementally maintainable materialized view
|
|
HINT: sublink only supports subquery with EXISTS clause in WHERE clause
|
|
SELECT pgivm.create_immv('mv_ivm_subquery', 'SELECT * FROM mv_base_a a WHERE true and CASE EXISTS(SELECT 1 FROM mv_base_b b WHERE a.i = b.i) WHEN true THEN false ELSE true END');
|
|
ERROR: this query is not allowed on incrementally maintainable materialized view
|
|
HINT: sublink only supports subquery with EXISTS clause in WHERE clause
|
|
-- support join subquery in FROM clause
|
|
BEGIN;
|
|
SELECT pgivm.create_immv('mv_ivm_join_subquery', 'SELECT i, j, k FROM ( SELECT i, a.j, b.k FROM mv_base_b b INNER JOIN mv_base_a a USING(i)) tmp');
|
|
NOTICE: could not create an index on immv "mv_ivm_join_subquery" automatically
|
|
DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause.
|
|
HINT: Create an index on the immv for efficient incremental maintenance.
|
|
create_immv
|
|
-------------
|
|
4
|
|
(1 row)
|
|
|
|
WITH
|
|
ai AS (INSERT INTO mv_base_a VALUES (1,11),(2,22) RETURNING 0),
|
|
bi AS (INSERT INTO mv_base_b VALUES (1,111),(3,133) RETURNING 0),
|
|
bd AS (DELETE FROM mv_base_b WHERE i = 4 RETURNING 0)
|
|
SELECT;
|
|
--
|
|
(1 row)
|
|
|
|
SELECT * FROM mv_ivm_join_subquery ORDER BY i,j,k;
|
|
i | j | k
|
|
---+----+-----
|
|
1 | 10 | 101
|
|
1 | 10 | 111
|
|
1 | 11 | 101
|
|
1 | 11 | 111
|
|
2 | 20 | 102
|
|
2 | 22 | 102
|
|
3 | 30 | 103
|
|
3 | 30 | 133
|
|
(8 rows)
|
|
|
|
ROLLBACK;
|
|
BEGIN;
|
|
-- nested subquery
|
|
SELECT pgivm.create_immv('mv_ivm_join_subquery', 'SELECT i, j, k FROM ( SELECT i, a.j, b.k FROM mv_base_b b INNER JOIN (SELECT * FROM mv_base_a) a USING(i)) tmp');
|
|
NOTICE: could not create an index on immv "mv_ivm_join_subquery" automatically
|
|
DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause.
|
|
HINT: Create an index on the immv for efficient incremental maintenance.
|
|
create_immv
|
|
-------------
|
|
4
|
|
(1 row)
|
|
|
|
WITH
|
|
ai AS (INSERT INTO mv_base_a VALUES (1,11),(2,22) RETURNING 0),
|
|
bi AS (INSERT INTO mv_base_b VALUES (1,111),(3,133) RETURNING 0),
|
|
bd AS (DELETE FROM mv_base_b WHERE i = 4 RETURNING 0)
|
|
SELECT;
|
|
--
|
|
(1 row)
|
|
|
|
SELECT * FROM mv_ivm_join_subquery ORDER BY i,j,k;
|
|
i | j | k
|
|
---+----+-----
|
|
1 | 10 | 101
|
|
1 | 10 | 111
|
|
1 | 11 | 101
|
|
1 | 11 | 111
|
|
2 | 20 | 102
|
|
2 | 22 | 102
|
|
3 | 30 | 103
|
|
3 | 30 | 133
|
|
(8 rows)
|
|
|
|
ROLLBACK;
|
|
-- support simple CTE
|
|
BEGIN;
|
|
SELECT pgivm.create_immv('mv_cte',
|
|
'WITH b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i');
|
|
NOTICE: could not create an index on immv "mv_cte" automatically
|
|
DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause.
|
|
HINT: Create an index on the immv for efficient incremental maintenance.
|
|
create_immv
|
|
-------------
|
|
4
|
|
(1 row)
|
|
|
|
INSERT INTO mv_base_a VALUES(2,20);
|
|
INSERT INTO mv_base_b VALUES(3,300);
|
|
SELECT * FROM mv_cte ORDER BY i,j;
|
|
i | j
|
|
---+----
|
|
1 | 10
|
|
2 | 20
|
|
2 | 20
|
|
3 | 30
|
|
3 | 30
|
|
4 | 40
|
|
(6 rows)
|
|
|
|
ROLLBACK;
|
|
BEGIN;
|
|
SELECT pgivm.create_immv('mv_cte',
|
|
'WITH a AS (SELECT * FROM mv_base_a), b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM a, b WHERE a.i = b.i');
|
|
NOTICE: could not create an index on immv "mv_cte" automatically
|
|
DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause.
|
|
HINT: Create an index on the immv for efficient incremental maintenance.
|
|
create_immv
|
|
-------------
|
|
4
|
|
(1 row)
|
|
|
|
INSERT INTO mv_base_a VALUES(2,20);
|
|
INSERT INTO mv_base_b VALUES(3,300);
|
|
SELECT * FROM mv_cte ORDER BY i,j;
|
|
i | j
|
|
---+----
|
|
1 | 10
|
|
2 | 20
|
|
2 | 20
|
|
3 | 30
|
|
3 | 30
|
|
4 | 40
|
|
(6 rows)
|
|
|
|
ROLLBACK;
|
|
BEGIN;
|
|
SELECT pgivm.create_immv('mv_cte',
|
|
'WITH b AS ( SELECT * FROM mv_base_b) SELECT v.i,v.j FROM (WITH a AS (SELECT * FROM mv_base_a) SELECT a.i,a.j FROM a, b WHERE a.i = b.i) v');
|
|
NOTICE: could not create an index on immv "mv_cte" automatically
|
|
DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause.
|
|
HINT: Create an index on the immv for efficient incremental maintenance.
|
|
create_immv
|
|
-------------
|
|
4
|
|
(1 row)
|
|
|
|
INSERT INTO mv_base_a VALUES(2,20);
|
|
INSERT INTO mv_base_b VALUES(3,300);
|
|
SELECT * FROM mv_cte ORDER BY i,j;
|
|
i | j
|
|
---+----
|
|
1 | 10
|
|
2 | 20
|
|
2 | 20
|
|
3 | 30
|
|
3 | 30
|
|
4 | 40
|
|
(6 rows)
|
|
|
|
ROLLBACK;
|
|
BEGIN;
|
|
SELECT pgivm.create_immv('mv_cte',
|
|
'SELECT * FROM (WITH a AS (SELECT * FROM mv_base_a), b AS ( SELECT * FROM mv_base_b) SELECT a.i,a.j FROM a, b WHERE a.i = b.i) v');
|
|
NOTICE: could not create an index on immv "mv_cte" automatically
|
|
DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause.
|
|
HINT: Create an index on the immv for efficient incremental maintenance.
|
|
create_immv
|
|
-------------
|
|
4
|
|
(1 row)
|
|
|
|
INSERT INTO mv_base_a VALUES(2,20);
|
|
INSERT INTO mv_base_b VALUES(3,300);
|
|
SELECT * FROM mv_cte ORDER BY i,j;
|
|
i | j
|
|
---+----
|
|
1 | 10
|
|
2 | 20
|
|
2 | 20
|
|
3 | 30
|
|
3 | 30
|
|
4 | 40
|
|
(6 rows)
|
|
|
|
ROLLBACK;
|
|
BEGIN;
|
|
SELECT pgivm.create_immv('mv_cte',
|
|
'WITH b AS ( SELECT * FROM (SELECT * FROM mv_base_b) b2) SELECT v.i,v.j FROM (WITH a AS (SELECT * FROM mv_base_a) SELECT a.i,a.j FROM a, b WHERE a.i = b.i) v');
|
|
NOTICE: could not create an index on immv "mv_cte" automatically
|
|
DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause.
|
|
HINT: Create an index on the immv for efficient incremental maintenance.
|
|
create_immv
|
|
-------------
|
|
4
|
|
(1 row)
|
|
|
|
INSERT INTO mv_base_a VALUES(2,20);
|
|
INSERT INTO mv_base_b VALUES(3,300);
|
|
SELECT * FROM mv_cte ORDER BY i,j;
|
|
i | j
|
|
---+----
|
|
1 | 10
|
|
2 | 20
|
|
2 | 20
|
|
3 | 30
|
|
3 | 30
|
|
4 | 40
|
|
(6 rows)
|
|
|
|
ROLLBACK;
|
|
BEGIN;
|
|
SELECT pgivm.create_immv('mv_cte',
|
|
'WITH x AS ( SELECT i, a.j, b.k FROM mv_base_b b INNER JOIN mv_base_a a USING(i)) SELECT * FROM x');
|
|
NOTICE: could not create an index on immv "mv_cte" automatically
|
|
DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause.
|
|
HINT: Create an index on the immv for efficient incremental maintenance.
|
|
create_immv
|
|
-------------
|
|
4
|
|
(1 row)
|
|
|
|
WITH
|
|
ai AS (INSERT INTO mv_base_a VALUES (1,11),(2,22) RETURNING 0),
|
|
bi AS (INSERT INTO mv_base_b VALUES (1,111),(3,133) RETURNING 0),
|
|
bd AS (DELETE FROM mv_base_b WHERE i = 4 RETURNING 0)
|
|
SELECT;
|
|
--
|
|
(1 row)
|
|
|
|
SELECT * FROM mv_cte ORDER BY i,j,k;
|
|
i | j | k
|
|
---+----+-----
|
|
1 | 10 | 101
|
|
1 | 10 | 111
|
|
1 | 11 | 101
|
|
1 | 11 | 111
|
|
2 | 20 | 102
|
|
2 | 22 | 102
|
|
3 | 30 | 103
|
|
3 | 30 | 133
|
|
(8 rows)
|
|
|
|
ROLLBACK;
|
|
-- nested CTE
|
|
BEGIN;
|
|
SELECT pgivm.create_immv('mv_ivm_nested_cte', 'WITH v AS ( WITH a AS (SELECT * FROM mv_base_a) SELECT i, a.j, b.k FROM mv_base_b b INNER JOIN a USING(i)) SELECT * FROM v');
|
|
NOTICE: could not create an index on immv "mv_ivm_nested_cte" automatically
|
|
DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause.
|
|
HINT: Create an index on the immv for efficient incremental maintenance.
|
|
create_immv
|
|
-------------
|
|
4
|
|
(1 row)
|
|
|
|
WITH
|
|
ai AS (INSERT INTO mv_base_a VALUES (1,11),(2,22) RETURNING 0),
|
|
bi AS (INSERT INTO mv_base_b VALUES (1,111),(3,133) RETURNING 0),
|
|
bd AS (DELETE FROM mv_base_b WHERE i = 4 RETURNING 0)
|
|
SELECT;
|
|
--
|
|
(1 row)
|
|
|
|
SELECT * FROM mv_ivm_nested_cte ORDER BY i,j,k;
|
|
i | j | k
|
|
---+----+-----
|
|
1 | 10 | 101
|
|
1 | 10 | 111
|
|
1 | 11 | 101
|
|
1 | 11 | 111
|
|
2 | 20 | 102
|
|
2 | 22 | 102
|
|
3 | 30 | 103
|
|
3 | 30 | 133
|
|
(8 rows)
|
|
|
|
ROLLBACK;
|
|
-- Multiply-referenced CTE
|
|
BEGIN;
|
|
CREATE TABLE base_t (i int, v int);
|
|
INSERT INTO base_t VALUES (1, 10), (2, 20), (3, 30);
|
|
SELECT pgivm.create_immv('mv_cte_multi(v1, v2)',
|
|
'WITH t AS (SELECT * FROM base_t) SELECT t1.v, t2.v FROM t AS t1 JOIN t AS t2 ON t1.i = t2.i');
|
|
NOTICE: could not create an index on immv "mv_cte_multi" automatically
|
|
DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause.
|
|
HINT: Create an index on the immv for efficient incremental maintenance.
|
|
create_immv
|
|
-------------
|
|
3
|
|
(1 row)
|
|
|
|
SELECT * FROM mv_cte_multi 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_cte_multi 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_cte_multi ORDER BY v1;
|
|
v1 | v2
|
|
-----+-----
|
|
50 | 50
|
|
60 | 60
|
|
130 | 130
|
|
300 | 300
|
|
(4 rows)
|
|
|
|
ROLLBACK;
|
|
--- disallow not-simple CTE
|
|
SELECT pgivm.create_immv('mv_cte_fail', 'WITH b AS (SELECT i, COUNT(*) FROM mv_base_b GROUP BY i) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i');
|
|
ERROR: aggregate functions in nested query are not supported on incrementally maintainable materialized view
|
|
SELECT pgivm.create_immv('mv_cte_fail', 'WITH b AS (SELECT DISTINCT i FROM mv_base_b) SELECT a.i,a.j FROM mv_base_a a, b WHERE a.i = b.i');
|
|
ERROR: DISTINCT clause in nested query are not supported on incrementally maintainable materialized view
|
|
SELECT pgivm.create_immv('mv_cte_fail', 'WITH a AS (SELECT i, j FROM mv_base_a) SELECT a.i,a.j FROM a WHERE EXISTS(WITH b AS (SELECT i FROM mv_base_b) SELECT 1 FROM b WHERE a.i = b.i)');
|
|
ERROR: CTE in EXIST clause is not supported on incrementally maintainable materialized view
|
|
-- unreferenced CTE
|
|
SELECT pgivm.create_immv('mv_cte_fail', 'WITH b AS (SELECT * FROM mv_base_b) SELECT * FROM mv_base_a a');
|
|
ERROR: Ureferenced WITH query is not supported on incrementally maintainable materialized view
|
|
-- views including NULL
|
|
BEGIN;
|
|
CREATE TABLE base_t (i int, v int);
|
|
INSERT INTO base_t VALUES (1,10),(2, NULL);
|
|
SELECT pgivm.create_immv('mv', 'SELECT * FROM base_t');
|
|
NOTICE: could not create an index on immv "mv" automatically
|
|
DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause.
|
|
HINT: Create an index on the immv for efficient incremental maintenance.
|
|
create_immv
|
|
-------------
|
|
2
|
|
(1 row)
|
|
|
|
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);
|
|
SELECT pgivm.create_immv('mv', 'SELECT * FROM base_t');
|
|
NOTICE: could not create an index on immv "mv" automatically
|
|
DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause.
|
|
HINT: Create an index on the immv for efficient incremental maintenance.
|
|
create_immv
|
|
-------------
|
|
0
|
|
(1 row)
|
|
|
|
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);
|
|
SELECT pgivm.create_immv('mv', 'SELECT i, sum(v) FROM base_t GROUP BY i');
|
|
NOTICE: created index "mv_index" on immv "mv"
|
|
create_immv
|
|
-------------
|
|
2
|
|
(1 row)
|
|
|
|
SELECT * FROM mv ORDER BY i;
|
|
i | sum | __ivm_count_sum__ | __ivm_count__
|
|
---+-----+-------------------+---------------
|
|
1 | 30 | 2 | 2
|
|
| 3 | 2 | 2
|
|
(2 rows)
|
|
|
|
UPDATE base_t SET v = v * 10;
|
|
SELECT * FROM mv ORDER BY i;
|
|
i | sum | __ivm_count_sum__ | __ivm_count__
|
|
---+-----+-------------------+---------------
|
|
1 | 300 | 2 | 2
|
|
| 30 | 2 | 2
|
|
(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);
|
|
SELECT pgivm.create_immv('mv', 'SELECT i, min(v), max(v) FROM base_t GROUP BY i');
|
|
NOTICE: created index "mv_index" on immv "mv"
|
|
create_immv
|
|
-------------
|
|
1
|
|
(1 row)
|
|
|
|
SELECT * FROM mv ORDER BY i;
|
|
i | min | max | __ivm_count_min__ | __ivm_count_max__ | __ivm_count__
|
|
---+-----+-----+-------------------+-------------------+---------------
|
|
| 1 | 5 | 5 | 5 | 5
|
|
(1 row)
|
|
|
|
DELETE FROM base_t WHERE v = 1;
|
|
SELECT * FROM mv ORDER BY i;
|
|
i | min | max | __ivm_count_min__ | __ivm_count_max__ | __ivm_count__
|
|
---+-----+-----+-------------------+-------------------+---------------
|
|
| 2 | 5 | 4 | 4 | 4
|
|
(1 row)
|
|
|
|
DELETE FROM base_t WHERE v = 3;
|
|
SELECT * FROM mv ORDER BY i;
|
|
i | min | max | __ivm_count_min__ | __ivm_count_max__ | __ivm_count__
|
|
---+-----+-----+-------------------+-------------------+---------------
|
|
| 2 | 5 | 3 | 3 | 3
|
|
(1 row)
|
|
|
|
DELETE FROM base_t WHERE v = 5;
|
|
SELECT * FROM mv ORDER BY i;
|
|
i | min | max | __ivm_count_min__ | __ivm_count_max__ | __ivm_count__
|
|
---+-----+-----+-------------------+-------------------+---------------
|
|
| 2 | 4 | 2 | 2 | 2
|
|
(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);
|
|
SELECT pgivm.create_immv('mv_mytype',
|
|
'SELECT * FROM t_mytype');
|
|
NOTICE: could not create an index on immv "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 immv for efficient incremental maintenance.
|
|
create_immv
|
|
-------------
|
|
0
|
|
(1 row)
|
|
|
|
INSERT INTO t_mytype VALUES ('1'::mytype);
|
|
SELECT * FROM mv_mytype;
|
|
x
|
|
---
|
|
1
|
|
(1 row)
|
|
|
|
ROLLBACK;
|
|
-- outer join is not supported
|
|
SELECT pgivm.create_immv('mv(a,b)',
|
|
'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
|
|
-- contain system column
|
|
SELECT pgivm.create_immv('mv_ivm01', 'SELECT i,j,xmin FROM mv_base_a');
|
|
ERROR: system column is not supported on incrementally maintainable materialized view
|
|
SELECT pgivm.create_immv('mv_ivm02', 'SELECT i,j FROM mv_base_a WHERE xmin = ''610''');
|
|
ERROR: system column is not supported on incrementally maintainable materialized view
|
|
SELECT pgivm.create_immv('mv_ivm03', 'SELECT i,j,xmin::text AS x_min FROM mv_base_a');
|
|
ERROR: system column is not supported on incrementally maintainable materialized view
|
|
SELECT pgivm.create_immv('mv_ivm04', 'SELECT i,j,xidsend(xmin) AS x_min FROM mv_base_a');
|
|
ERROR: system column is not supported on incrementally maintainable materialized view
|
|
-- contain ORDER BY
|
|
SELECT pgivm.create_immv('mv_ivm07', '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
|
|
SELECT pgivm.create_immv('mv_ivm08', '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 GROUP BY without aggregate
|
|
SELECT pgivm.create_immv('mv_ivm08', 'SELECT i,j FROM mv_base_a GROUP BY i,j');
|
|
ERROR: GROUP BY clause without aggregate 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;
|
|
SELECT pgivm.create_immv('mv_ivm07', '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
|
|
SELECT pgivm.create_immv('mv_ivm08', '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
|
|
-- contain mutable functions
|
|
SELECT pgivm.create_immv('mv_ivm12', '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
|
|
SELECT pgivm.create_immv('mv_ivm13', '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
|
|
SELECT pgivm.create_immv('mv_ivm14', '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
|
|
SELECT pgivm.create_immv('mv_ivm15', '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
|
|
SELECT pgivm.create_immv('mv_ivm16', '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
|
|
SELECT pgivm.create_immv('mv_ivm17', 'SELECT COUNT(*) FILTER(WHERE i < 3) FROM mv_base_a');
|
|
ERROR: aggregate function with FILTER clause is not supported on incrementally maintainable materialized view
|
|
SELECT pgivm.create_immv('mv_ivm18', 'SELECT COUNT(DISTINCT i) FROM mv_base_a');
|
|
ERROR: aggregate function with DISTINCT arguments is not supported on incrementally maintainable materialized view
|
|
SELECT pgivm.create_immv('mv_ivm19', '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
|
|
SELECT pgivm.create_immv('mv_ivm20', '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);
|
|
SELECT pgivm.create_immv('mv_ivm21', 'SELECT * FROM parent');
|
|
ERROR: inheritance parent is not supported on incrementally maintainable materialized view
|
|
ROLLBACK;
|
|
-- UNION statement is not supported
|
|
SELECT pgivm.create_immv('mv_ivm22', '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
|
|
-- DISTINCT clause in nested query are not supported
|
|
SELECT pgivm.create_immv('mv_ivm23', 'SELECT * FROM (SELECT DISTINCT i,j FROM mv_base_a) AS tmp');;
|
|
ERROR: DISTINCT clause in nested query are not supported on incrementally maintainable materialized view
|
|
-- empty target list is not allowed with IVM
|
|
SELECT pgivm.create_immv('mv_ivm25', 'SELECT FROM mv_base_a');
|
|
ERROR: empty target list is not supported on incrementally maintainable materialized view
|
|
-- FOR UPDATE/SHARE is not supported
|
|
SELECT pgivm.create_immv('mv_ivm26', 'SELECT i,j FROM mv_base_a FOR UPDATE');
|
|
ERROR: FOR UPDATE/SHARE clause is not supported on incrementally maintainable materialized view
|
|
SELECT pgivm.create_immv('mv_ivm27', 'SELECT * FROM (SELECT i,j FROM mv_base_a FOR UPDATE) AS tmp;');
|
|
ERROR: FOR UPDATE/SHARE clause is not supported on incrementally maintainable materialized view
|
|
-- tartget list cannot contain ivm column that start with '__ivm'
|
|
SELECT pgivm.create_immv('mv_ivm28', '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.
|
|
SELECT pgivm.create_immv('mv_ivm29', '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
|
|
SELECT pgivm.create_immv('mv_ivm30', 'SELECT sum(i)*0.5 FROM mv_base_a');
|
|
ERROR: expression containing an aggregate in it is not supported on incrementally maintainable materialized view
|
|
SELECT pgivm.create_immv('mv_ivm31', '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
|
|
SELECT pgivm.create_immv('mv_ivm_only_values1', 'values(1)');
|
|
ERROR: VALUES is not supported on incrementally maintainable materialized view
|
|
SELECT pgivm.create_immv('mv_ivm_only_values2', 'SELECT * FROM (values(1)) AS tmp');
|
|
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;
|
|
SELECT pgivm.create_immv('ivm_rls', 'SELECT * FROM rls_tbl');
|
|
NOTICE: could not create an index on immv "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 immv for efficient incremental maintenance.
|
|
create_immv
|
|
-------------
|
|
1
|
|
(1 row)
|
|
|
|
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;
|
|
SELECT pgivm.create_immv('ivm_rls2', 'SELECT * FROM rls_tbl JOIN num_tbl USING(id)');
|
|
NOTICE: could not create an index on immv "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 immv for efficient incremental maintenance.
|
|
create_immv
|
|
-------------
|
|
3
|
|
(1 row)
|
|
|
|
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)
|
|
|
|
DROP TABLE rls_tbl CASCADE;
|
|
NOTICE: drop cascades to 2 other objects
|
|
DETAIL: drop cascades to table ivm_rls
|
|
drop cascades to table ivm_rls2
|
|
DROP TABLE num_tbl CASCADE;
|
|
DROP USER regress_ivm_user;
|
|
DROP USER regress_ivm_admin;
|
|
-- 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
|
|
SELECT pgivm.create_immv('mv_idx1', 'SELECT i, sum(j) FROM base_a GROUP BY i');
|
|
NOTICE: created index "mv_idx1_index" on immv "mv_idx1"
|
|
create_immv
|
|
-------------
|
|
0
|
|
(1 row)
|
|
|
|
--- distinct: create an index
|
|
SELECT pgivm.create_immv('mv_idx2', 'SELECT DISTINCT j FROM base_a');
|
|
NOTICE: created index "mv_idx2_index" on immv "mv_idx2"
|
|
create_immv
|
|
-------------
|
|
0
|
|
(1 row)
|
|
|
|
--- with all pkey columns: create an index
|
|
SELECT pgivm.create_immv('mv_idx3(i_a, i_b)', 'SELECT a.i, b.i FROM base_a a, base_b b');
|
|
NOTICE: created index "mv_idx3_index" on immv "mv_idx3"
|
|
create_immv
|
|
-------------
|
|
0
|
|
(1 row)
|
|
|
|
--- missing some pkey columns: no index
|
|
SELECT pgivm.create_immv('mv_idx4', 'SELECT j FROM base_a');
|
|
NOTICE: could not create an index on immv "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 immv for efficient incremental maintenance.
|
|
create_immv
|
|
-------------
|
|
0
|
|
(1 row)
|
|
|
|
SELECT pgivm.create_immv('mv_idx5', 'SELECT a.i, b.j FROM base_a a, base_b b');
|
|
NOTICE: could not create an index on immv "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 immv for efficient incremental maintenance.
|
|
create_immv
|
|
-------------
|
|
0
|
|
(1 row)
|
|
|
|
--- subqueries: create an index
|
|
SELECT pgivm.create_immv('mv_idx6(i_a, i_b)', 'SELECT a.i, b.i FROM (SELECT * FROM base_a) a, (SELECT * FROM base_b) b');
|
|
NOTICE: created index "mv_idx6_index" on immv "mv_idx6"
|
|
create_immv
|
|
-------------
|
|
0
|
|
(1 row)
|
|
|
|
--- with set-returning function: no index
|
|
SELECT pgivm.create_immv('mv_idx7', 'SELECT i FROM base_a, generate_series(1,10)');
|
|
NOTICE: could not create an index on immv "mv_idx7" automatically
|
|
DETAIL: This target list does not have all the primary key columns, or this view does not contain GROUP BY or DISTINCT clause.
|
|
HINT: Create an index on the immv for efficient incremental maintenance.
|
|
create_immv
|
|
-------------
|
|
0
|
|
(1 row)
|
|
|
|
ROLLBACK;
|
|
-- type that doesn't have default operator class for access method btree
|
|
BEGIN;
|
|
CREATE TABLE table_json (j json);
|
|
SELECT pgivm.create_immv('mv_json', 'SELECT * from table_json');
|
|
ERROR: data type json has no default operator class for access method "btree"
|
|
ROLLBACK;
|
|
-- prevent IMMV chanages
|
|
INSERT INTO mv_ivm_1 VALUES(1,1,1);
|
|
ERROR: cannot change materialized view "mv_ivm_1"
|
|
UPDATE mv_ivm_1 SET k = 1 WHERE i = 1;
|
|
ERROR: cannot change materialized view "mv_ivm_1"
|
|
DELETE FROM mv_ivm_1;
|
|
ERROR: cannot change materialized view "mv_ivm_1"
|
|
TRUNCATE mv_ivm_1;
|
|
ERROR: cannot change materialized view "mv_ivm_1"
|
|
-- get_immv_def function
|
|
SELECT immvrelid, pgivm.get_immv_def(immvrelid) FROM pgivm.pg_ivm_immv ORDER BY 1;
|
|
immvrelid | get_immv_def
|
|
-----------+----------------------------------
|
|
mv_ivm_1 | SELECT a.i, +
|
|
| a.j, +
|
|
| b.k +
|
|
| FROM (mv_base_a a +
|
|
| JOIN mv_base_b b USING (i))
|
|
(1 row)
|
|
|
|
-- mv_base_b is not immv
|
|
SELECT 'mv_base_b'::regclass, pgivm.get_immv_def('mv_base_b');
|
|
regclass | get_immv_def
|
|
-----------+--------------
|
|
mv_base_b |
|
|
(1 row)
|
|
|
|
DROP TABLE mv_base_b CASCADE;
|
|
NOTICE: drop cascades to 3 other objects
|
|
DETAIL: drop cascades to table mv_ivm_1
|
|
drop cascades to view b_view
|
|
drop cascades to materialized view b_mview
|
|
DROP TABLE mv_base_a CASCADE;
|