Fix a bug introduced by 5b8b2f0, which built targetlist of subquery substituting
modified table. When a table has a column whose name includes a capital letter,
incremental view maintenance failed because crafted targetlist contains incorrect
column name which was parsed as lower case.
Isseu #124
1743 lines
62 KiB
Text
1743 lines
62 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
|
|
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 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;
|
|
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 | 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;
|
|
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 | ivm_user | two
|
|
3 | baz_2 | ivm_user | three_2
|
|
6 | corge | 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 ivm_user;
|
|
DROP USER 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;
|