Consider tuple duplicity in maintenance of EXISTS views
When a tuple is inserted into a table in an EXISTS subquery, the duplicity of row is computed by count(*), but it was not considered and only one tuple was inserted with ignoring the duplicity. This is fixed by duplicating rows as much as the duplicity by using generate_series at inserting. (Issue #82)
This commit is contained in:
parent
aab9db3605
commit
8c3b4ba9d7
3 changed files with 36 additions and 2 deletions
|
|
@ -828,6 +828,19 @@ SELECT * FROM mv_ivm_exists_subquery2 ORDER BY i, j;
|
|||
4 | 40 | 1
|
||||
(4 rows)
|
||||
|
||||
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)
|
||||
|
||||
ROLLBACK;
|
||||
-- support simple subquery in FROM clause
|
||||
BEGIN;
|
||||
|
|
|
|||
22
matview.c
22
matview.c
|
|
@ -2523,6 +2523,7 @@ apply_new_delta_with_count(const char *matviewname, const char* deltaname_new,
|
|||
StringInfoData returning_keys;
|
||||
ListCell *lc;
|
||||
char *match_cond = "";
|
||||
StringInfoData deltaname_new_for_insert;
|
||||
|
||||
/* build WHERE condition for searching tuples to be updated */
|
||||
match_cond = get_matching_condition_string(keys);
|
||||
|
|
@ -2543,6 +2544,24 @@ apply_new_delta_with_count(const char *matviewname, const char* deltaname_new,
|
|||
else
|
||||
appendStringInfo(&returning_keys, "NULL");
|
||||
|
||||
/*
|
||||
* If count_colname is not "__ivm_count__", the view contains EXISTS
|
||||
* subquery and the count column to be updated here is "__ivm_exists_count_*"
|
||||
* that stores the number of columns generated by corresponding EXISTS
|
||||
* 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.
|
||||
*/
|
||||
initStringInfo(&deltaname_new_for_insert);
|
||||
if (!strcmp(count_colname, "__ivm_count__"))
|
||||
appendStringInfo(&deltaname_new_for_insert, "%s", deltaname_new);
|
||||
else
|
||||
appendStringInfo(&deltaname_new_for_insert,
|
||||
"(SELECT diff.* FROM %s diff,"
|
||||
"pg_catalog.generate_series(1, diff.\"__ivm_count__\"))",
|
||||
deltaname_new);
|
||||
|
||||
/* Search for matching tuples from the view and update if found or insert if not. */
|
||||
initStringInfo(&querybuf);
|
||||
appendStringInfo(&querybuf,
|
||||
|
|
@ -2561,9 +2580,8 @@ apply_new_delta_with_count(const char *matviewname, const char* deltaname_new,
|
|||
match_cond,
|
||||
returning_keys.data,
|
||||
matviewname, target_list->data,
|
||||
target_list->data, deltaname_new,
|
||||
target_list->data, deltaname_new_for_insert.data,
|
||||
match_cond);
|
||||
|
||||
if (SPI_exec(querybuf.data, 0) != SPI_OK_INSERT)
|
||||
elog(ERROR, "SPI_exec failed: %s", querybuf.data);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -269,6 +269,9 @@ 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;
|
||||
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;
|
||||
ROLLBACK;
|
||||
|
||||
-- support simple subquery in FROM clause
|
||||
|
|
|
|||
Loading…
Reference in a new issue