diff --git a/expected/pg_ivm.out b/expected/pg_ivm.out index 4252f62..a62dc63 100644 --- a/expected/pg_ivm.out +++ b/expected/pg_ivm.out @@ -828,6 +828,14 @@ SELECT * FROM mv_ivm_exists_subquery2 ORDER BY i, j; 4 | 40 | 1 (4 rows) +--- EXISTS subquery with tuple duplication and DISTINCT +SELECT 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; @@ -841,6 +849,15 @@ SELECT * FROM mv_ivm_exists_subquery ORDER BY i, j; 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; diff --git a/matview.c b/matview.c index 11a7e13..6f8525b 100644 --- a/matview.c +++ b/matview.c @@ -195,7 +195,7 @@ static void apply_new_delta(const char *matviewname, const char *deltaname_new, StringInfo target_list); static void apply_new_delta_with_count(const char *matviewname, const char* deltaname_new, List *keys, StringInfo target_list, StringInfo aggs_set, - const char* count_colname); + const char* count_colname, bool distinct); static char *get_matching_condition_string(List *keys); static char *get_returning_string(List *minmax_list, List *is_min_list, List *keys); static char *get_minmax_recalc_condition_string(List *minmax_list, List *is_min_list); @@ -2033,7 +2033,8 @@ apply_delta(Oid matviewOid, Tuplestorestate *old_tuplestores, Tuplestorestate *n /* apply new delta */ if (use_count) apply_new_delta_with_count(matviewname, NEW_DELTA_ENRNAME, - keys, aggs_set_new, &target_list_buf, count_colname); + keys, aggs_set_new, &target_list_buf, count_colname, + query->distinctClause != NULL); else apply_new_delta(matviewname, NEW_DELTA_ENRNAME, &target_list_buf); } @@ -2517,7 +2518,7 @@ apply_old_delta(const char *matviewname, const char *deltaname_old, static void apply_new_delta_with_count(const char *matviewname, const char* deltaname_new, List *keys, StringInfo aggs_set, StringInfo target_list, - const char* count_colname) + const char* count_colname, bool distinct) { StringInfoData querybuf; StringInfoData returning_keys; @@ -2525,6 +2526,7 @@ apply_new_delta_with_count(const char *matviewname, const char* deltaname_new, char *match_cond = ""; StringInfoData deltaname_new_for_insert; + /* build WHERE condition for searching tuples to be updated */ match_cond = get_matching_condition_string(keys); @@ -2551,10 +2553,10 @@ apply_new_delta_with_count(const char *matviewname, const char* deltaname_new, * subquery for each row in the view. In this case, __ivm_count__ in * deltaname_new stores duplicity of rows, and each row need to be * duplicated as much as __ivm_count__ by using generate_series at - * inserting. + * inserting if DISTINCT is not used. */ initStringInfo(&deltaname_new_for_insert); - if (!strcmp(count_colname, "__ivm_count__")) + if (!strcmp(count_colname, "__ivm_count__") || distinct) appendStringInfo(&deltaname_new_for_insert, "%s", deltaname_new); else appendStringInfo(&deltaname_new_for_insert, diff --git a/sql/pg_ivm.sql b/sql/pg_ivm.sql index 8294e07..87adf90 100644 --- a/sql/pg_ivm.sql +++ b/sql/pg_ivm.sql @@ -269,9 +269,12 @@ 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; SELECT * FROM mv_ivm_exists_subquery2 ORDER BY i, j; +--- EXISTS subquery with tuple duplication and DISTINCT +SELECT 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)'); 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; +SELECT * FROM mv_ivm_exists_subquery_distinct ORDER BY i, j; ROLLBACK; -- support simple subquery in FROM clause @@ -295,7 +298,6 @@ SELECT create_immv('mv_ivm_subquery', 'SELECT a.j FROM mv_base_a a WHERE EXISTS( SELECT create_immv('mv_ivm_subquery', 'SELECT EXISTS(SELECT 1 from mv_base_b) FROM mv_base_a a'); SELECT create_immv('mv_ivm_subquery', 'SELECT false OR EXISTS(SELECT 1 FROM mv_base_a) FROM mv_base_b'); SELECT 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'); - -- support join subquery in FROM clause BEGIN; SELECT 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');