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 | 40 | 1
|
||||||
(4 rows)
|
(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;
|
ROLLBACK;
|
||||||
-- support simple subquery in FROM clause
|
-- support simple subquery in FROM clause
|
||||||
BEGIN;
|
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;
|
StringInfoData returning_keys;
|
||||||
ListCell *lc;
|
ListCell *lc;
|
||||||
char *match_cond = "";
|
char *match_cond = "";
|
||||||
|
StringInfoData deltaname_new_for_insert;
|
||||||
|
|
||||||
/* build WHERE condition for searching tuples to be updated */
|
/* build WHERE condition for searching tuples to be updated */
|
||||||
match_cond = get_matching_condition_string(keys);
|
match_cond = get_matching_condition_string(keys);
|
||||||
|
|
@ -2543,6 +2544,24 @@ apply_new_delta_with_count(const char *matviewname, const char* deltaname_new,
|
||||||
else
|
else
|
||||||
appendStringInfo(&returning_keys, "NULL");
|
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. */
|
/* Search for matching tuples from the view and update if found or insert if not. */
|
||||||
initStringInfo(&querybuf);
|
initStringInfo(&querybuf);
|
||||||
appendStringInfo(&querybuf,
|
appendStringInfo(&querybuf,
|
||||||
|
|
@ -2561,9 +2580,8 @@ apply_new_delta_with_count(const char *matviewname, const char* deltaname_new,
|
||||||
match_cond,
|
match_cond,
|
||||||
returning_keys.data,
|
returning_keys.data,
|
||||||
matviewname, target_list->data,
|
matviewname, target_list->data,
|
||||||
target_list->data, deltaname_new,
|
target_list->data, deltaname_new_for_insert.data,
|
||||||
match_cond);
|
match_cond);
|
||||||
|
|
||||||
if (SPI_exec(querybuf.data, 0) != SPI_OK_INSERT)
|
if (SPI_exec(querybuf.data, 0) != SPI_OK_INSERT)
|
||||||
elog(ERROR, "SPI_exec failed: %s", querybuf.data);
|
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;
|
DELETE FROM mv_base_b WHERE i = 2;
|
||||||
SELECT * FROM mv_ivm_exists_subquery ORDER BY i, j;
|
SELECT * FROM mv_ivm_exists_subquery ORDER BY i, j;
|
||||||
SELECT * FROM mv_ivm_exists_subquery2 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;
|
ROLLBACK;
|
||||||
|
|
||||||
-- support simple subquery in FROM clause
|
-- support simple subquery in FROM clause
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue