Fix potential view inconsistency issues (#121)
Previously, the view contents could become inconsistent with the base tables in the following scenarios: 1) A concurrent transaction modifies a base table and commits before the incremental view maintenance starts in the current transaction. 2) A concurrent transaction modifies a base table and commits before the create_immv or refresh_immv command generates data. 3) Concurrent transactions incrementally update a view with a self-join or modify multiple base tables simultaneously. Incremental updates of a view are generally performed sequentially using an exclusive lock. However, even if we are able to acquire the lock, a concurrent transaction may have already incrementally updated the view and been committed before we can acquire it. In REPEATABLE READ or SERIALIZABLE isolation levels, this could lead to an inconsistent view state, which is the cause of the first issue. To fix this, a new field, lastivmupdate, has been added to the pg_ivm_immv catalog to record the transaction ID of the most recent update to the view. Before performing view maintenance, the transaction ID is checked. If the transaction was still in progress at the start of the current transaction, an error is raised to prevent anomalies. To fix the second issue, the timing of CreateTrigger() has been moved to before data generation. This ensures that locks conflicting with table modifications have been acquired on all base tables. In addition, the latest snapshot is used in READ COMMITTED level during the data generation to reflect committed changes from concurrent transactions. Additionally, inconsistencies that cannot be avoided through locking are prevented by checking the transaction ID of the last view update, as done for the first issue. However, concurrent table modifications and create_immv execution still cannot be detected at the time of view creation. Therefore, create_immv raises a warning in REPEATABLE READ or SERIALIZABLE isolation levels, suggesting that the command be used in READ COMMITTED mode or that refresh_immv be executed afterward to ensure the view remains consistent. The third issue was caused by the snapshot used for checking tuple visibility in the table's pre-update state not being the latest one. To fix this, the latest snapshot is now used in READ COMMITTED mode. Isolation tests are also added. Issue #104
This commit is contained in:
parent
5b8b2f0a82
commit
f1166c0421
26 changed files with 3725 additions and 39 deletions
5
Makefile
5
Makefile
|
|
@ -20,6 +20,11 @@ DATA = pg_ivm--1.0.sql \
|
|||
|
||||
REGRESS = pg_ivm create_immv refresh_immv
|
||||
|
||||
ISOLATION = create_insert refresh_insert insert_insert \
|
||||
create_insert2 refresh_insert2 insert_insert2 \
|
||||
create_insert3 refresh_insert3 insert_insert3
|
||||
ISOLATION_OPTS = --load-extension=pg_ivm
|
||||
|
||||
PG_CONFIG ?= pg_config
|
||||
PGXS := $(shell $(PG_CONFIG) --pgxs)
|
||||
include $(PGXS)
|
||||
|
|
|
|||
14
README.md
14
README.md
|
|
@ -94,6 +94,8 @@ pgivim.create_immv(immv_name text, view_definition text) RETURNS bigint
|
|||
|
||||
When an IMMV is created, some triggers are automatically created so that the view's contents are immediately updated when its base tables are modified. In addition, a unique index is created on the IMMV automatically if possible. If the view definition query has a GROUP BY clause, a unique index is created on the columns of GROUP BY expressions. Also, if the view has DISTINCT clause, a unique index is created on all columns in the target list. Otherwise, if the IMMV contains all primary key attributes of its base tables in the target list, a unique index is created on these attributes. In other cases, no index is created.
|
||||
|
||||
`create_immv` acquires an `AccessExclusiveLock` on the view. However, even if we are able to acquire the lock, a concurrent transaction may have already incrementally updated and committed the view before we can acquire it. In the `REPEATABLE READ` or `SERIALIZABLE` isolation levels, this could lead to an inconsistent state of the view. Unfortunately, this situation cannot be detected during the creation of the view. As a result, `create_immv` raises a warning in these isolation levels, suggesting that the command be used in `READ COMMITTED` or that `refresh_immv` be executed afterward to make the view's contents remain consistent.
|
||||
|
||||
Note that if you use PostgreSQL 17 or later, while `create_immv` is running, the `search_path` is temporarily changed to `pg_catalog, pg_temp`.
|
||||
|
||||
#### refresh_immv
|
||||
|
|
@ -107,6 +109,8 @@ pgivm.refresh_immv(immv_name text, with_data bool) RETURNS bigint
|
|||
|
||||
The with_data flag is corresponding to `WITH [NO] DATA` option of REFRESH MATERIALIZED VIEW` command. If with_data is true, the backing query is executed to provide the new data, and if the IMMV is unpopulated, triggers for maintaining the view are created. Also, a unique index is created for IMMV if it is possible and the view doesn't have that yet. If with_data is false, no new data is generated and the IMMV become unpopulated, and the triggers are dropped from the IMMV. Note that unpopulated IMMV is still scannable although the result is empty. This behaviour may be changed in future to raise an error when an unpopulated IMMV is scanned.
|
||||
|
||||
`refresh_immv` acquires `AccessExclusiveLock` on the view. However, even if we are able to acquire the lock, a concurrent transaction may have already incrementally updated and committed the view before we can acquire the lock. In `REPEATABLE READ` or `SERIALIZABLE` isolation level, this could lead to an inconsistent state of the view. Therefore, an error is raised to prevent anomalies when this situation is detected.
|
||||
|
||||
Note that if you use PostgreSQL 17 or later, while `refresh_immv` is running, the `search_path` is temporarily changed to `pg_catalog, pg_temp`.
|
||||
|
||||
#### get_immv_def
|
||||
|
|
@ -259,7 +263,15 @@ When a base table is truncated, the IMMV is also truncated and the contents beco
|
|||
|
||||
### Concurrent Transactions
|
||||
|
||||
Suppose an IMMV is defined on two base tables and each table was modified in different a concurrent transaction simultaneously. In the transaction which was committed first, the IMMV can be updated considering only the change which happened in this transaction. On the other hand, in order to update the IMMV correctly in the transaction which was committed later, we need to know the changes occurred in both transactions. For this reason, `ExclusiveLock` is held on an IMMV immediately after a base table is modified in `READ COMMITTED` mode to make sure that the IMMV is updated in the latter transaction after the former transaction is committed. In `REPEATABLE READ` or `SERIALIZABLE` mode, an error is raised immediately if lock acquisition fails because any changes which occurred in other transactions are not visible in these modes and IMMV cannot be updated correctly in such situations. However, as an exception if the IMMV has only one base table and doesn't use DISTINCT or GROUP BY, and the table is modified by `INSERT`, then the lock held on the IMMV is `RowExclusiveLock`.
|
||||
Incremental updates of a view are basically performed in sequentially even with concurrent transactions running.
|
||||
|
||||
Suppose an IMMV is defined on two base tables and each table is modified in different concurrent transactions simultaneously. In the transaction which was committed first, the IMMV can be updated considering only the change made in that transaction. However, to update the IMMV correctly in the transaction that commits later, we need to account for the changes made in both transactions.
|
||||
|
||||
For this reason, `ExclusiveLock` is held on an IMMV immediately after a base table is modified in `READ COMMITTED` isolation level. This ensures that the IMMV is updated in the latter transaction only after the former transaction has committed. In `REPEATABLE READ` or `SERIALIZABLE` isolation level, an error is raised immediately if lock acquisition fails, as changes made by other transactions are not visible in these levels, and the IMMV cannot be updated correctly in such situations.
|
||||
|
||||
However, as an exception if the IMMV has only one base table, does not use DISTINCT or GROUP BY, and is modified by `INSERT`, then the lock held on the IMMV is `RowExclusiveLock`.
|
||||
|
||||
Even if we are able to acquire a lock, a concurrent transaction may have already incrementally updated and committed the view before we can acquire the lock. In `REPEATABLE READ` or `SERIALIZABLE` isolation level, this could lead to an inconsistent state of the view. Therefore, an error is raised to prevent anomalies when this situation is detected.
|
||||
|
||||
### Row Level Security
|
||||
|
||||
|
|
|
|||
|
|
@ -285,7 +285,7 @@ ExecCreateImmv(ParseState *pstate, CreateTableAsStmt *stmt,
|
|||
{
|
||||
Relation matviewRel;
|
||||
|
||||
RefreshImmvByOid(address.objectId, false, pstate->p_sourcetext, qc);
|
||||
RefreshImmvByOid(address.objectId, true, false, pstate->p_sourcetext, qc);
|
||||
|
||||
if (qc)
|
||||
qc->commandTag = CMDTAG_SELECT;
|
||||
|
|
@ -299,6 +299,13 @@ ExecCreateImmv(ParseState *pstate, CreateTableAsStmt *stmt,
|
|||
CreateChangePreventTrigger(address.objectId);
|
||||
|
||||
table_close(matviewRel, NoLock);
|
||||
|
||||
if (IsolationUsesXactSnapshot())
|
||||
ereport(WARNING,
|
||||
(errmsg("inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ"),
|
||||
errdetail("The view may not include effects of a concurrent transaction."),
|
||||
errhint("create_immv should be used in isolation level READ COMMITTED, "
|
||||
"or execute refresh_immv to make sure the view is consistent.")));
|
||||
}
|
||||
|
||||
return address;
|
||||
|
|
|
|||
325
expected/create_insert.out
Normal file
325
expected/create_insert.out
Normal file
|
|
@ -0,0 +1,325 @@
|
|||
Parsed test spec with 2 sessions
|
||||
|
||||
starting permutation: s1 create s2 insert c1 check2 c2 mv
|
||||
step s1: SELECT;
|
||||
tx1: 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.
|
||||
step create:
|
||||
SELECT pgivm.create_immv('mv(x,y)', 'SELECT * FROM a a1, a a2 WHERE a1.i = a2.i');
|
||||
CREATE FUNCTION check_mv() RETURNS text AS
|
||||
$$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END
|
||||
FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL
|
||||
(SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) $$ LANGUAGE sql;
|
||||
|
||||
create_immv
|
||||
-----------
|
||||
1
|
||||
(1 row)
|
||||
|
||||
step s2: SELECT;
|
||||
step insert: INSERT INTO a VALUES (2); <waiting ...>
|
||||
step c1: COMMIT;
|
||||
step insert: <... completed>
|
||||
step check2: SELECT check_mv();
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
step c2: COMMIT;
|
||||
step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv();
|
||||
x|y
|
||||
-+-
|
||||
1|1
|
||||
2|2
|
||||
(2 rows)
|
||||
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
|
||||
starting permutation: s1 create s2 c1 insert check2 c2 mv
|
||||
step s1: SELECT;
|
||||
tx1: 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.
|
||||
step create:
|
||||
SELECT pgivm.create_immv('mv(x,y)', 'SELECT * FROM a a1, a a2 WHERE a1.i = a2.i');
|
||||
CREATE FUNCTION check_mv() RETURNS text AS
|
||||
$$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END
|
||||
FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL
|
||||
(SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) $$ LANGUAGE sql;
|
||||
|
||||
create_immv
|
||||
-----------
|
||||
1
|
||||
(1 row)
|
||||
|
||||
step s2: SELECT;
|
||||
step c1: COMMIT;
|
||||
step insert: INSERT INTO a VALUES (2);
|
||||
step check2: SELECT check_mv();
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
step c2: COMMIT;
|
||||
step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv();
|
||||
x|y
|
||||
-+-
|
||||
1|1
|
||||
2|2
|
||||
(2 rows)
|
||||
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
|
||||
starting permutation: s1 s2 create insert c1 check2 c2 mv
|
||||
step s1: SELECT;
|
||||
step s2: SELECT;
|
||||
tx1: 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.
|
||||
step create:
|
||||
SELECT pgivm.create_immv('mv(x,y)', 'SELECT * FROM a a1, a a2 WHERE a1.i = a2.i');
|
||||
CREATE FUNCTION check_mv() RETURNS text AS
|
||||
$$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END
|
||||
FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL
|
||||
(SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) $$ LANGUAGE sql;
|
||||
|
||||
create_immv
|
||||
-----------
|
||||
1
|
||||
(1 row)
|
||||
|
||||
step insert: INSERT INTO a VALUES (2); <waiting ...>
|
||||
step c1: COMMIT;
|
||||
step insert: <... completed>
|
||||
step check2: SELECT check_mv();
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
step c2: COMMIT;
|
||||
step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv();
|
||||
x|y
|
||||
-+-
|
||||
1|1
|
||||
2|2
|
||||
(2 rows)
|
||||
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
|
||||
starting permutation: s1 s2 insert create c2 check1 c1 mv
|
||||
step s1: SELECT;
|
||||
step s2: SELECT;
|
||||
step insert: INSERT INTO a VALUES (2);
|
||||
step create:
|
||||
SELECT pgivm.create_immv('mv(x,y)', 'SELECT * FROM a a1, a a2 WHERE a1.i = a2.i');
|
||||
CREATE FUNCTION check_mv() RETURNS text AS
|
||||
$$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END
|
||||
FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL
|
||||
(SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) $$ LANGUAGE sql;
|
||||
<waiting ...>
|
||||
step c2: COMMIT;
|
||||
tx1: 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.
|
||||
step create: <... completed>
|
||||
create_immv
|
||||
-----------
|
||||
2
|
||||
(1 row)
|
||||
|
||||
step check1: SELECT check_mv();
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
step c1: COMMIT;
|
||||
step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv();
|
||||
x|y
|
||||
-+-
|
||||
1|1
|
||||
2|2
|
||||
(2 rows)
|
||||
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
|
||||
starting permutation: s1 s2 create c1 insert check2 c2 mv
|
||||
step s1: SELECT;
|
||||
step s2: SELECT;
|
||||
tx1: 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.
|
||||
step create:
|
||||
SELECT pgivm.create_immv('mv(x,y)', 'SELECT * FROM a a1, a a2 WHERE a1.i = a2.i');
|
||||
CREATE FUNCTION check_mv() RETURNS text AS
|
||||
$$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END
|
||||
FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL
|
||||
(SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) $$ LANGUAGE sql;
|
||||
|
||||
create_immv
|
||||
-----------
|
||||
1
|
||||
(1 row)
|
||||
|
||||
step c1: COMMIT;
|
||||
step insert: INSERT INTO a VALUES (2);
|
||||
step check2: SELECT check_mv();
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
step c2: COMMIT;
|
||||
step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv();
|
||||
x|y
|
||||
-+-
|
||||
1|1
|
||||
2|2
|
||||
(2 rows)
|
||||
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
|
||||
starting permutation: s2 insert s1 create c2 check1 c1 mv
|
||||
step s2: SELECT;
|
||||
step insert: INSERT INTO a VALUES (2);
|
||||
step s1: SELECT;
|
||||
step create:
|
||||
SELECT pgivm.create_immv('mv(x,y)', 'SELECT * FROM a a1, a a2 WHERE a1.i = a2.i');
|
||||
CREATE FUNCTION check_mv() RETURNS text AS
|
||||
$$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END
|
||||
FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL
|
||||
(SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) $$ LANGUAGE sql;
|
||||
<waiting ...>
|
||||
step c2: COMMIT;
|
||||
tx1: 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.
|
||||
step create: <... completed>
|
||||
create_immv
|
||||
-----------
|
||||
2
|
||||
(1 row)
|
||||
|
||||
step check1: SELECT check_mv();
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
step c1: COMMIT;
|
||||
step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv();
|
||||
x|y
|
||||
-+-
|
||||
1|1
|
||||
2|2
|
||||
(2 rows)
|
||||
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
|
||||
starting permutation: s2 insert s1 c2 create check1 c1 mv
|
||||
step s2: SELECT;
|
||||
step insert: INSERT INTO a VALUES (2);
|
||||
step s1: SELECT;
|
||||
step c2: COMMIT;
|
||||
tx1: 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.
|
||||
step create:
|
||||
SELECT pgivm.create_immv('mv(x,y)', 'SELECT * FROM a a1, a a2 WHERE a1.i = a2.i');
|
||||
CREATE FUNCTION check_mv() RETURNS text AS
|
||||
$$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END
|
||||
FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL
|
||||
(SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) $$ LANGUAGE sql;
|
||||
|
||||
create_immv
|
||||
-----------
|
||||
2
|
||||
(1 row)
|
||||
|
||||
step check1: SELECT check_mv();
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
step c1: COMMIT;
|
||||
step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv();
|
||||
x|y
|
||||
-+-
|
||||
1|1
|
||||
2|2
|
||||
(2 rows)
|
||||
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
|
||||
starting permutation: s2 s1 insert c2 create check1 c1 mv
|
||||
step s2: SELECT;
|
||||
step s1: SELECT;
|
||||
step insert: INSERT INTO a VALUES (2);
|
||||
step c2: COMMIT;
|
||||
tx1: 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.
|
||||
step create:
|
||||
SELECT pgivm.create_immv('mv(x,y)', 'SELECT * FROM a a1, a a2 WHERE a1.i = a2.i');
|
||||
CREATE FUNCTION check_mv() RETURNS text AS
|
||||
$$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END
|
||||
FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL
|
||||
(SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) $$ LANGUAGE sql;
|
||||
|
||||
create_immv
|
||||
-----------
|
||||
2
|
||||
(1 row)
|
||||
|
||||
step check1: SELECT check_mv();
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
step c1: COMMIT;
|
||||
step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv();
|
||||
x|y
|
||||
-+-
|
||||
1|1
|
||||
2|2
|
||||
(2 rows)
|
||||
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
345
expected/create_insert2.out
Normal file
345
expected/create_insert2.out
Normal file
|
|
@ -0,0 +1,345 @@
|
|||
Parsed test spec with 2 sessions
|
||||
|
||||
starting permutation: s1 create s2 insert c1 check2 c2 mv
|
||||
step s1: SELECT;
|
||||
tx1: 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.
|
||||
tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ
|
||||
DETAIL: The view may not include effects of a concurrent transaction.
|
||||
HINT: create_immv should be used in isolation level READ COMMITTED, or execute refresh_immv to make sure the view is consistent.
|
||||
step create:
|
||||
SELECT pgivm.create_immv('mv(x,y)', 'SELECT * FROM a a1, a a2 WHERE a1.i = a2.i');
|
||||
CREATE FUNCTION check_mv() RETURNS text AS
|
||||
$$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END
|
||||
FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL
|
||||
(SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) $$ LANGUAGE sql;
|
||||
|
||||
create_immv
|
||||
-----------
|
||||
1
|
||||
(1 row)
|
||||
|
||||
step s2: SELECT;
|
||||
step insert: INSERT INTO a VALUES (2); <waiting ...>
|
||||
step c1: COMMIT;
|
||||
step insert: <... completed>
|
||||
step check2: SELECT check_mv();
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
step c2: COMMIT;
|
||||
step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv();
|
||||
x|y
|
||||
-+-
|
||||
1|1
|
||||
2|2
|
||||
(2 rows)
|
||||
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
|
||||
starting permutation: s1 create s2 c1 insert check2 c2 mv
|
||||
step s1: SELECT;
|
||||
tx1: 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.
|
||||
tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ
|
||||
DETAIL: The view may not include effects of a concurrent transaction.
|
||||
HINT: create_immv should be used in isolation level READ COMMITTED, or execute refresh_immv to make sure the view is consistent.
|
||||
step create:
|
||||
SELECT pgivm.create_immv('mv(x,y)', 'SELECT * FROM a a1, a a2 WHERE a1.i = a2.i');
|
||||
CREATE FUNCTION check_mv() RETURNS text AS
|
||||
$$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END
|
||||
FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL
|
||||
(SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) $$ LANGUAGE sql;
|
||||
|
||||
create_immv
|
||||
-----------
|
||||
1
|
||||
(1 row)
|
||||
|
||||
step s2: SELECT;
|
||||
step c1: COMMIT;
|
||||
step insert: INSERT INTO a VALUES (2);
|
||||
step check2: SELECT check_mv();
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
step c2: COMMIT;
|
||||
step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv();
|
||||
x|y
|
||||
-+-
|
||||
1|1
|
||||
2|2
|
||||
(2 rows)
|
||||
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
|
||||
starting permutation: s1 s2 create insert c1 check2 c2 mv
|
||||
step s1: SELECT;
|
||||
step s2: SELECT;
|
||||
tx1: 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.
|
||||
tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ
|
||||
DETAIL: The view may not include effects of a concurrent transaction.
|
||||
HINT: create_immv should be used in isolation level READ COMMITTED, or execute refresh_immv to make sure the view is consistent.
|
||||
step create:
|
||||
SELECT pgivm.create_immv('mv(x,y)', 'SELECT * FROM a a1, a a2 WHERE a1.i = a2.i');
|
||||
CREATE FUNCTION check_mv() RETURNS text AS
|
||||
$$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END
|
||||
FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL
|
||||
(SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) $$ LANGUAGE sql;
|
||||
|
||||
create_immv
|
||||
-----------
|
||||
1
|
||||
(1 row)
|
||||
|
||||
step insert: INSERT INTO a VALUES (2); <waiting ...>
|
||||
step c1: COMMIT;
|
||||
step insert: <... completed>
|
||||
step check2: SELECT check_mv();
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
step c2: COMMIT;
|
||||
step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv();
|
||||
x|y
|
||||
-+-
|
||||
1|1
|
||||
2|2
|
||||
(2 rows)
|
||||
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
|
||||
starting permutation: s1 s2 insert create c2 check1 c1 mv
|
||||
step s1: SELECT;
|
||||
step s2: SELECT;
|
||||
step insert: INSERT INTO a VALUES (2);
|
||||
step create:
|
||||
SELECT pgivm.create_immv('mv(x,y)', 'SELECT * FROM a a1, a a2 WHERE a1.i = a2.i');
|
||||
CREATE FUNCTION check_mv() RETURNS text AS
|
||||
$$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END
|
||||
FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL
|
||||
(SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) $$ LANGUAGE sql;
|
||||
<waiting ...>
|
||||
step c2: COMMIT;
|
||||
tx1: 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.
|
||||
tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ
|
||||
DETAIL: The view may not include effects of a concurrent transaction.
|
||||
HINT: create_immv should be used in isolation level READ COMMITTED, or execute refresh_immv to make sure the view is consistent.
|
||||
step create: <... completed>
|
||||
create_immv
|
||||
-----------
|
||||
1
|
||||
(1 row)
|
||||
|
||||
step check1: SELECT check_mv();
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
step c1: COMMIT;
|
||||
step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv();
|
||||
x|y
|
||||
-+-
|
||||
1|1
|
||||
(1 row)
|
||||
|
||||
check_mv
|
||||
--------
|
||||
ng
|
||||
(1 row)
|
||||
|
||||
|
||||
starting permutation: s1 s2 create c1 insert check2 c2 mv
|
||||
step s1: SELECT;
|
||||
step s2: SELECT;
|
||||
tx1: 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.
|
||||
tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ
|
||||
DETAIL: The view may not include effects of a concurrent transaction.
|
||||
HINT: create_immv should be used in isolation level READ COMMITTED, or execute refresh_immv to make sure the view is consistent.
|
||||
step create:
|
||||
SELECT pgivm.create_immv('mv(x,y)', 'SELECT * FROM a a1, a a2 WHERE a1.i = a2.i');
|
||||
CREATE FUNCTION check_mv() RETURNS text AS
|
||||
$$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END
|
||||
FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL
|
||||
(SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) $$ LANGUAGE sql;
|
||||
|
||||
create_immv
|
||||
-----------
|
||||
1
|
||||
(1 row)
|
||||
|
||||
step c1: COMMIT;
|
||||
step insert: INSERT INTO a VALUES (2);
|
||||
step check2: SELECT check_mv();
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
step c2: COMMIT;
|
||||
step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv();
|
||||
x|y
|
||||
-+-
|
||||
1|1
|
||||
2|2
|
||||
(2 rows)
|
||||
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
|
||||
starting permutation: s2 insert s1 create c2 check1 c1 mv
|
||||
step s2: SELECT;
|
||||
step insert: INSERT INTO a VALUES (2);
|
||||
step s1: SELECT;
|
||||
step create:
|
||||
SELECT pgivm.create_immv('mv(x,y)', 'SELECT * FROM a a1, a a2 WHERE a1.i = a2.i');
|
||||
CREATE FUNCTION check_mv() RETURNS text AS
|
||||
$$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END
|
||||
FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL
|
||||
(SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) $$ LANGUAGE sql;
|
||||
<waiting ...>
|
||||
step c2: COMMIT;
|
||||
tx1: 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.
|
||||
tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ
|
||||
DETAIL: The view may not include effects of a concurrent transaction.
|
||||
HINT: create_immv should be used in isolation level READ COMMITTED, or execute refresh_immv to make sure the view is consistent.
|
||||
step create: <... completed>
|
||||
create_immv
|
||||
-----------
|
||||
1
|
||||
(1 row)
|
||||
|
||||
step check1: SELECT check_mv();
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
step c1: COMMIT;
|
||||
step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv();
|
||||
x|y
|
||||
-+-
|
||||
1|1
|
||||
(1 row)
|
||||
|
||||
check_mv
|
||||
--------
|
||||
ng
|
||||
(1 row)
|
||||
|
||||
|
||||
starting permutation: s2 insert s1 c2 create check1 c1 mv
|
||||
step s2: SELECT;
|
||||
step insert: INSERT INTO a VALUES (2);
|
||||
step s1: SELECT;
|
||||
step c2: COMMIT;
|
||||
tx1: 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.
|
||||
tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ
|
||||
DETAIL: The view may not include effects of a concurrent transaction.
|
||||
HINT: create_immv should be used in isolation level READ COMMITTED, or execute refresh_immv to make sure the view is consistent.
|
||||
step create:
|
||||
SELECT pgivm.create_immv('mv(x,y)', 'SELECT * FROM a a1, a a2 WHERE a1.i = a2.i');
|
||||
CREATE FUNCTION check_mv() RETURNS text AS
|
||||
$$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END
|
||||
FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL
|
||||
(SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) $$ LANGUAGE sql;
|
||||
|
||||
create_immv
|
||||
-----------
|
||||
1
|
||||
(1 row)
|
||||
|
||||
step check1: SELECT check_mv();
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
step c1: COMMIT;
|
||||
step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv();
|
||||
x|y
|
||||
-+-
|
||||
1|1
|
||||
(1 row)
|
||||
|
||||
check_mv
|
||||
--------
|
||||
ng
|
||||
(1 row)
|
||||
|
||||
|
||||
starting permutation: s2 s1 insert c2 create check1 c1 mv
|
||||
step s2: SELECT;
|
||||
step s1: SELECT;
|
||||
step insert: INSERT INTO a VALUES (2);
|
||||
step c2: COMMIT;
|
||||
tx1: 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.
|
||||
tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ
|
||||
DETAIL: The view may not include effects of a concurrent transaction.
|
||||
HINT: create_immv should be used in isolation level READ COMMITTED, or execute refresh_immv to make sure the view is consistent.
|
||||
step create:
|
||||
SELECT pgivm.create_immv('mv(x,y)', 'SELECT * FROM a a1, a a2 WHERE a1.i = a2.i');
|
||||
CREATE FUNCTION check_mv() RETURNS text AS
|
||||
$$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END
|
||||
FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL
|
||||
(SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) $$ LANGUAGE sql;
|
||||
|
||||
create_immv
|
||||
-----------
|
||||
1
|
||||
(1 row)
|
||||
|
||||
step check1: SELECT check_mv();
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
step c1: COMMIT;
|
||||
step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv();
|
||||
x|y
|
||||
-+-
|
||||
1|1
|
||||
(1 row)
|
||||
|
||||
check_mv
|
||||
--------
|
||||
ng
|
||||
(1 row)
|
||||
|
||||
329
expected/create_insert3.out
Normal file
329
expected/create_insert3.out
Normal file
|
|
@ -0,0 +1,329 @@
|
|||
Parsed test spec with 2 sessions
|
||||
|
||||
starting permutation: s1 create s2 insert c1 check2 c2 mv
|
||||
step s1: SELECT;
|
||||
tx1: 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.
|
||||
tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ
|
||||
DETAIL: The view may not include effects of a concurrent transaction.
|
||||
HINT: create_immv should be used in isolation level READ COMMITTED, or execute refresh_immv to make sure the view is consistent.
|
||||
step create:
|
||||
SELECT pgivm.create_immv('mv(x,y)', 'SELECT * FROM a a1, a a2 WHERE a1.i = a2.i');
|
||||
CREATE FUNCTION check_mv() RETURNS text AS
|
||||
$$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END
|
||||
FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL
|
||||
(SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) $$ LANGUAGE sql;
|
||||
|
||||
create_immv
|
||||
-----------
|
||||
1
|
||||
(1 row)
|
||||
|
||||
step s2: SELECT;
|
||||
step insert: INSERT INTO a VALUES (2); <waiting ...>
|
||||
step c1: COMMIT;
|
||||
step insert: <... completed>
|
||||
ERROR: could not serialize access due to read/write dependencies among transactions
|
||||
step check2: SELECT check_mv();
|
||||
ERROR: current transaction is aborted, commands ignored until end of transaction block
|
||||
step c2: COMMIT;
|
||||
step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv();
|
||||
x|y
|
||||
-+-
|
||||
1|1
|
||||
(1 row)
|
||||
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
|
||||
starting permutation: s1 create s2 c1 insert check2 c2 mv
|
||||
step s1: SELECT;
|
||||
tx1: 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.
|
||||
tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ
|
||||
DETAIL: The view may not include effects of a concurrent transaction.
|
||||
HINT: create_immv should be used in isolation level READ COMMITTED, or execute refresh_immv to make sure the view is consistent.
|
||||
step create:
|
||||
SELECT pgivm.create_immv('mv(x,y)', 'SELECT * FROM a a1, a a2 WHERE a1.i = a2.i');
|
||||
CREATE FUNCTION check_mv() RETURNS text AS
|
||||
$$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END
|
||||
FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL
|
||||
(SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) $$ LANGUAGE sql;
|
||||
|
||||
create_immv
|
||||
-----------
|
||||
1
|
||||
(1 row)
|
||||
|
||||
step s2: SELECT;
|
||||
step c1: COMMIT;
|
||||
step insert: INSERT INTO a VALUES (2);
|
||||
ERROR: could not serialize access due to read/write dependencies among transactions
|
||||
step check2: SELECT check_mv();
|
||||
ERROR: current transaction is aborted, commands ignored until end of transaction block
|
||||
step c2: COMMIT;
|
||||
step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv();
|
||||
x|y
|
||||
-+-
|
||||
1|1
|
||||
(1 row)
|
||||
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
|
||||
starting permutation: s1 s2 create insert c1 check2 c2 mv
|
||||
step s1: SELECT;
|
||||
step s2: SELECT;
|
||||
tx1: 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.
|
||||
tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ
|
||||
DETAIL: The view may not include effects of a concurrent transaction.
|
||||
HINT: create_immv should be used in isolation level READ COMMITTED, or execute refresh_immv to make sure the view is consistent.
|
||||
step create:
|
||||
SELECT pgivm.create_immv('mv(x,y)', 'SELECT * FROM a a1, a a2 WHERE a1.i = a2.i');
|
||||
CREATE FUNCTION check_mv() RETURNS text AS
|
||||
$$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END
|
||||
FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL
|
||||
(SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) $$ LANGUAGE sql;
|
||||
|
||||
create_immv
|
||||
-----------
|
||||
1
|
||||
(1 row)
|
||||
|
||||
step insert: INSERT INTO a VALUES (2); <waiting ...>
|
||||
step c1: COMMIT;
|
||||
step insert: <... completed>
|
||||
ERROR: could not serialize access due to read/write dependencies among transactions
|
||||
step check2: SELECT check_mv();
|
||||
ERROR: current transaction is aborted, commands ignored until end of transaction block
|
||||
step c2: COMMIT;
|
||||
step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv();
|
||||
x|y
|
||||
-+-
|
||||
1|1
|
||||
(1 row)
|
||||
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
|
||||
starting permutation: s1 s2 insert create c2 check1 c1 mv
|
||||
step s1: SELECT;
|
||||
step s2: SELECT;
|
||||
step insert: INSERT INTO a VALUES (2);
|
||||
step create:
|
||||
SELECT pgivm.create_immv('mv(x,y)', 'SELECT * FROM a a1, a a2 WHERE a1.i = a2.i');
|
||||
CREATE FUNCTION check_mv() RETURNS text AS
|
||||
$$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END
|
||||
FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL
|
||||
(SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) $$ LANGUAGE sql;
|
||||
<waiting ...>
|
||||
step c2: COMMIT;
|
||||
tx1: 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.
|
||||
tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ
|
||||
DETAIL: The view may not include effects of a concurrent transaction.
|
||||
HINT: create_immv should be used in isolation level READ COMMITTED, or execute refresh_immv to make sure the view is consistent.
|
||||
step create: <... completed>
|
||||
create_immv
|
||||
-----------
|
||||
1
|
||||
(1 row)
|
||||
|
||||
step check1: SELECT check_mv();
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
step c1: COMMIT;
|
||||
step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv();
|
||||
x|y
|
||||
-+-
|
||||
1|1
|
||||
(1 row)
|
||||
|
||||
check_mv
|
||||
--------
|
||||
ng
|
||||
(1 row)
|
||||
|
||||
|
||||
starting permutation: s1 s2 create c1 insert check2 c2 mv
|
||||
step s1: SELECT;
|
||||
step s2: SELECT;
|
||||
tx1: 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.
|
||||
tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ
|
||||
DETAIL: The view may not include effects of a concurrent transaction.
|
||||
HINT: create_immv should be used in isolation level READ COMMITTED, or execute refresh_immv to make sure the view is consistent.
|
||||
step create:
|
||||
SELECT pgivm.create_immv('mv(x,y)', 'SELECT * FROM a a1, a a2 WHERE a1.i = a2.i');
|
||||
CREATE FUNCTION check_mv() RETURNS text AS
|
||||
$$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END
|
||||
FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL
|
||||
(SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) $$ LANGUAGE sql;
|
||||
|
||||
create_immv
|
||||
-----------
|
||||
1
|
||||
(1 row)
|
||||
|
||||
step c1: COMMIT;
|
||||
step insert: INSERT INTO a VALUES (2);
|
||||
ERROR: could not serialize access due to read/write dependencies among transactions
|
||||
step check2: SELECT check_mv();
|
||||
ERROR: current transaction is aborted, commands ignored until end of transaction block
|
||||
step c2: COMMIT;
|
||||
step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv();
|
||||
x|y
|
||||
-+-
|
||||
1|1
|
||||
(1 row)
|
||||
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
|
||||
starting permutation: s2 insert s1 create c2 check1 c1 mv
|
||||
step s2: SELECT;
|
||||
step insert: INSERT INTO a VALUES (2);
|
||||
step s1: SELECT;
|
||||
step create:
|
||||
SELECT pgivm.create_immv('mv(x,y)', 'SELECT * FROM a a1, a a2 WHERE a1.i = a2.i');
|
||||
CREATE FUNCTION check_mv() RETURNS text AS
|
||||
$$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END
|
||||
FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL
|
||||
(SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) $$ LANGUAGE sql;
|
||||
<waiting ...>
|
||||
step c2: COMMIT;
|
||||
tx1: 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.
|
||||
tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ
|
||||
DETAIL: The view may not include effects of a concurrent transaction.
|
||||
HINT: create_immv should be used in isolation level READ COMMITTED, or execute refresh_immv to make sure the view is consistent.
|
||||
step create: <... completed>
|
||||
create_immv
|
||||
-----------
|
||||
1
|
||||
(1 row)
|
||||
|
||||
step check1: SELECT check_mv();
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
step c1: COMMIT;
|
||||
step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv();
|
||||
x|y
|
||||
-+-
|
||||
1|1
|
||||
(1 row)
|
||||
|
||||
check_mv
|
||||
--------
|
||||
ng
|
||||
(1 row)
|
||||
|
||||
|
||||
starting permutation: s2 insert s1 c2 create check1 c1 mv
|
||||
step s2: SELECT;
|
||||
step insert: INSERT INTO a VALUES (2);
|
||||
step s1: SELECT;
|
||||
step c2: COMMIT;
|
||||
tx1: 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.
|
||||
tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ
|
||||
DETAIL: The view may not include effects of a concurrent transaction.
|
||||
HINT: create_immv should be used in isolation level READ COMMITTED, or execute refresh_immv to make sure the view is consistent.
|
||||
step create:
|
||||
SELECT pgivm.create_immv('mv(x,y)', 'SELECT * FROM a a1, a a2 WHERE a1.i = a2.i');
|
||||
CREATE FUNCTION check_mv() RETURNS text AS
|
||||
$$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END
|
||||
FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL
|
||||
(SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) $$ LANGUAGE sql;
|
||||
|
||||
create_immv
|
||||
-----------
|
||||
1
|
||||
(1 row)
|
||||
|
||||
step check1: SELECT check_mv();
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
step c1: COMMIT;
|
||||
step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv();
|
||||
x|y
|
||||
-+-
|
||||
1|1
|
||||
(1 row)
|
||||
|
||||
check_mv
|
||||
--------
|
||||
ng
|
||||
(1 row)
|
||||
|
||||
|
||||
starting permutation: s2 s1 insert c2 create check1 c1 mv
|
||||
step s2: SELECT;
|
||||
step s1: SELECT;
|
||||
step insert: INSERT INTO a VALUES (2);
|
||||
step c2: COMMIT;
|
||||
tx1: 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.
|
||||
tx1: WARNING: inconsistent view can be created in isolation level SERIALIZABLE or REPEATABLE READ
|
||||
DETAIL: The view may not include effects of a concurrent transaction.
|
||||
HINT: create_immv should be used in isolation level READ COMMITTED, or execute refresh_immv to make sure the view is consistent.
|
||||
step create:
|
||||
SELECT pgivm.create_immv('mv(x,y)', 'SELECT * FROM a a1, a a2 WHERE a1.i = a2.i');
|
||||
CREATE FUNCTION check_mv() RETURNS text AS
|
||||
$$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END
|
||||
FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL
|
||||
(SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) $$ LANGUAGE sql;
|
||||
|
||||
create_immv
|
||||
-----------
|
||||
1
|
||||
(1 row)
|
||||
|
||||
step check1: SELECT check_mv();
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
step c1: COMMIT;
|
||||
step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv();
|
||||
x|y
|
||||
-+-
|
||||
1|1
|
||||
(1 row)
|
||||
|
||||
check_mv
|
||||
--------
|
||||
ng
|
||||
(1 row)
|
||||
|
||||
497
expected/insert_insert.out
Normal file
497
expected/insert_insert.out
Normal file
|
|
@ -0,0 +1,497 @@
|
|||
Parsed test spec with 2 sessions
|
||||
|
||||
starting permutation: s1 update1 s2 update2 c1 check2 c2 mv
|
||||
step s1: SELECT;
|
||||
step update1: UPDATE a SET j = 11 WHERE i = 1;
|
||||
step s2: SELECT;
|
||||
step update2: UPDATE b SET j = 111 WHERE i = 1; <waiting ...>
|
||||
step c1: COMMIT;
|
||||
step update2: <... completed>
|
||||
step check2: SELECT check_mv();
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
step c2: COMMIT;
|
||||
step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv();
|
||||
x| y| z
|
||||
--+--+---
|
||||
11|11|111
|
||||
(1 row)
|
||||
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
|
||||
starting permutation: s1 update1 s2 c1 update2 check2 c2 mv
|
||||
step s1: SELECT;
|
||||
step update1: UPDATE a SET j = 11 WHERE i = 1;
|
||||
step s2: SELECT;
|
||||
step c1: COMMIT;
|
||||
step update2: UPDATE b SET j = 111 WHERE i = 1;
|
||||
step check2: SELECT check_mv();
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
step c2: COMMIT;
|
||||
step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv();
|
||||
x| y| z
|
||||
--+--+---
|
||||
11|11|111
|
||||
(1 row)
|
||||
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
|
||||
starting permutation: s1 s2 update1 update2 c1 check2 c2 mv
|
||||
step s1: SELECT;
|
||||
step s2: SELECT;
|
||||
step update1: UPDATE a SET j = 11 WHERE i = 1;
|
||||
step update2: UPDATE b SET j = 111 WHERE i = 1; <waiting ...>
|
||||
step c1: COMMIT;
|
||||
step update2: <... completed>
|
||||
step check2: SELECT check_mv();
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
step c2: COMMIT;
|
||||
step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv();
|
||||
x| y| z
|
||||
--+--+---
|
||||
11|11|111
|
||||
(1 row)
|
||||
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
|
||||
starting permutation: s1 s2 update2 update1 c2 check1 c1 mv
|
||||
step s1: SELECT;
|
||||
step s2: SELECT;
|
||||
step update2: UPDATE b SET j = 111 WHERE i = 1;
|
||||
step update1: UPDATE a SET j = 11 WHERE i = 1; <waiting ...>
|
||||
step c2: COMMIT;
|
||||
step update1: <... completed>
|
||||
step check1: SELECT check_mv();
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
step c1: COMMIT;
|
||||
step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv();
|
||||
x| y| z
|
||||
--+--+---
|
||||
11|11|111
|
||||
(1 row)
|
||||
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
|
||||
starting permutation: s1 s2 update1 c1 update2 check2 c2 mv
|
||||
step s1: SELECT;
|
||||
step s2: SELECT;
|
||||
step update1: UPDATE a SET j = 11 WHERE i = 1;
|
||||
step c1: COMMIT;
|
||||
step update2: UPDATE b SET j = 111 WHERE i = 1;
|
||||
step check2: SELECT check_mv();
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
step c2: COMMIT;
|
||||
step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv();
|
||||
x| y| z
|
||||
--+--+---
|
||||
11|11|111
|
||||
(1 row)
|
||||
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
|
||||
starting permutation: s2 update2 s1 update1 c2 check1 c1 mv
|
||||
step s2: SELECT;
|
||||
step update2: UPDATE b SET j = 111 WHERE i = 1;
|
||||
step s1: SELECT;
|
||||
step update1: UPDATE a SET j = 11 WHERE i = 1; <waiting ...>
|
||||
step c2: COMMIT;
|
||||
step update1: <... completed>
|
||||
step check1: SELECT check_mv();
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
step c1: COMMIT;
|
||||
step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv();
|
||||
x| y| z
|
||||
--+--+---
|
||||
11|11|111
|
||||
(1 row)
|
||||
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
|
||||
starting permutation: s2 update2 s1 c2 update1 check1 c1 mv
|
||||
step s2: SELECT;
|
||||
step update2: UPDATE b SET j = 111 WHERE i = 1;
|
||||
step s1: SELECT;
|
||||
step c2: COMMIT;
|
||||
step update1: UPDATE a SET j = 11 WHERE i = 1;
|
||||
step check1: SELECT check_mv();
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
step c1: COMMIT;
|
||||
step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv();
|
||||
x| y| z
|
||||
--+--+---
|
||||
11|11|111
|
||||
(1 row)
|
||||
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
|
||||
starting permutation: s2 s1 update2 c2 update1 check1 c1 mv
|
||||
step s2: SELECT;
|
||||
step s1: SELECT;
|
||||
step update2: UPDATE b SET j = 111 WHERE i = 1;
|
||||
step c2: COMMIT;
|
||||
step update1: UPDATE a SET j = 11 WHERE i = 1;
|
||||
step check1: SELECT check_mv();
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
step c1: COMMIT;
|
||||
step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv();
|
||||
x| y| z
|
||||
--+--+---
|
||||
11|11|111
|
||||
(1 row)
|
||||
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
|
||||
starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv
|
||||
step s1: SELECT;
|
||||
step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200);
|
||||
step s2: SELECT;
|
||||
step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); <waiting ...>
|
||||
step c1: COMMIT;
|
||||
step insert2: <... completed>
|
||||
step check2: SELECT check_mv();
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
step c2: COMMIT;
|
||||
step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv();
|
||||
x| y| z
|
||||
--+--+---
|
||||
10|10|100
|
||||
10|11|100
|
||||
11|10|100
|
||||
11|11|100
|
||||
20|20|200
|
||||
20|20|201
|
||||
20|21|200
|
||||
20|21|201
|
||||
21|20|200
|
||||
21|20|201
|
||||
21|21|200
|
||||
21|21|201
|
||||
(12 rows)
|
||||
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
|
||||
starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv
|
||||
step s1: SELECT;
|
||||
step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200);
|
||||
step s2: SELECT;
|
||||
step c1: COMMIT;
|
||||
step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201);
|
||||
step check2: SELECT check_mv();
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
step c2: COMMIT;
|
||||
step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv();
|
||||
x| y| z
|
||||
--+--+---
|
||||
10|10|100
|
||||
10|11|100
|
||||
11|10|100
|
||||
11|11|100
|
||||
20|20|200
|
||||
20|20|201
|
||||
20|21|200
|
||||
20|21|201
|
||||
21|20|200
|
||||
21|20|201
|
||||
21|21|200
|
||||
21|21|201
|
||||
(12 rows)
|
||||
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
|
||||
starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv
|
||||
step s1: SELECT;
|
||||
step s2: SELECT;
|
||||
step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200);
|
||||
step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); <waiting ...>
|
||||
step c1: COMMIT;
|
||||
step insert2: <... completed>
|
||||
step check2: SELECT check_mv();
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
step c2: COMMIT;
|
||||
step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv();
|
||||
x| y| z
|
||||
--+--+---
|
||||
10|10|100
|
||||
10|11|100
|
||||
11|10|100
|
||||
11|11|100
|
||||
20|20|200
|
||||
20|20|201
|
||||
20|21|200
|
||||
20|21|201
|
||||
21|20|200
|
||||
21|20|201
|
||||
21|21|200
|
||||
21|21|201
|
||||
(12 rows)
|
||||
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
|
||||
starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv
|
||||
step s1: SELECT;
|
||||
step s2: SELECT;
|
||||
step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201);
|
||||
step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); <waiting ...>
|
||||
step c2: COMMIT;
|
||||
step insert1: <... completed>
|
||||
step check1: SELECT check_mv();
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
step c1: COMMIT;
|
||||
step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv();
|
||||
x| y| z
|
||||
--+--+---
|
||||
10|10|100
|
||||
10|11|100
|
||||
11|10|100
|
||||
11|11|100
|
||||
20|20|200
|
||||
20|20|201
|
||||
20|21|200
|
||||
20|21|201
|
||||
21|20|200
|
||||
21|20|201
|
||||
21|21|200
|
||||
21|21|201
|
||||
(12 rows)
|
||||
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
|
||||
starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv
|
||||
step s1: SELECT;
|
||||
step s2: SELECT;
|
||||
step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200);
|
||||
step c1: COMMIT;
|
||||
step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201);
|
||||
step check2: SELECT check_mv();
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
step c2: COMMIT;
|
||||
step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv();
|
||||
x| y| z
|
||||
--+--+---
|
||||
10|10|100
|
||||
10|11|100
|
||||
11|10|100
|
||||
11|11|100
|
||||
20|20|200
|
||||
20|20|201
|
||||
20|21|200
|
||||
20|21|201
|
||||
21|20|200
|
||||
21|20|201
|
||||
21|21|200
|
||||
21|21|201
|
||||
(12 rows)
|
||||
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
|
||||
starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv
|
||||
step s2: SELECT;
|
||||
step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201);
|
||||
step s1: SELECT;
|
||||
step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); <waiting ...>
|
||||
step c2: COMMIT;
|
||||
step insert1: <... completed>
|
||||
step check1: SELECT check_mv();
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
step c1: COMMIT;
|
||||
step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv();
|
||||
x| y| z
|
||||
--+--+---
|
||||
10|10|100
|
||||
10|11|100
|
||||
11|10|100
|
||||
11|11|100
|
||||
20|20|200
|
||||
20|20|201
|
||||
20|21|200
|
||||
20|21|201
|
||||
21|20|200
|
||||
21|20|201
|
||||
21|21|200
|
||||
21|21|201
|
||||
(12 rows)
|
||||
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
|
||||
starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv
|
||||
step s2: SELECT;
|
||||
step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201);
|
||||
step s1: SELECT;
|
||||
step c2: COMMIT;
|
||||
step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200);
|
||||
step check1: SELECT check_mv();
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
step c1: COMMIT;
|
||||
step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv();
|
||||
x| y| z
|
||||
--+--+---
|
||||
10|10|100
|
||||
10|11|100
|
||||
11|10|100
|
||||
11|11|100
|
||||
20|20|200
|
||||
20|20|201
|
||||
20|21|200
|
||||
20|21|201
|
||||
21|20|200
|
||||
21|20|201
|
||||
21|21|200
|
||||
21|21|201
|
||||
(12 rows)
|
||||
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
|
||||
starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv
|
||||
step s2: SELECT;
|
||||
step s1: SELECT;
|
||||
step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201);
|
||||
step c2: COMMIT;
|
||||
step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200);
|
||||
step check1: SELECT check_mv();
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
step c1: COMMIT;
|
||||
step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv();
|
||||
x| y| z
|
||||
--+--+---
|
||||
10|10|100
|
||||
10|11|100
|
||||
11|10|100
|
||||
11|11|100
|
||||
20|20|200
|
||||
20|20|201
|
||||
20|21|200
|
||||
20|21|201
|
||||
21|20|200
|
||||
21|20|201
|
||||
21|21|200
|
||||
21|21|201
|
||||
(12 rows)
|
||||
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
373
expected/insert_insert2.out
Normal file
373
expected/insert_insert2.out
Normal file
|
|
@ -0,0 +1,373 @@
|
|||
Parsed test spec with 2 sessions
|
||||
|
||||
starting permutation: s1 update1 s2 update2 c1 check2 c2 mv
|
||||
step s1: SELECT;
|
||||
step update1: UPDATE a SET j = 11 WHERE i = 1;
|
||||
step s2: SELECT;
|
||||
step update2: UPDATE b SET j = 111 WHERE i = 1;
|
||||
ERROR: could not obtain lock on materialized view "mv" during incremental maintenance
|
||||
step c1: COMMIT;
|
||||
step check2: SELECT check_mv();
|
||||
ERROR: current transaction is aborted, commands ignored until end of transaction block
|
||||
step c2: COMMIT;
|
||||
step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv();
|
||||
x| y| z
|
||||
--+--+---
|
||||
11|11|100
|
||||
(1 row)
|
||||
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
|
||||
starting permutation: s1 update1 s2 c1 update2 check2 c2 mv
|
||||
step s1: SELECT;
|
||||
step update1: UPDATE a SET j = 11 WHERE i = 1;
|
||||
step s2: SELECT;
|
||||
step c1: COMMIT;
|
||||
step update2: UPDATE b SET j = 111 WHERE i = 1;
|
||||
ERROR: the materialized view is incrementally updated in concurrent transaction
|
||||
step check2: SELECT check_mv();
|
||||
ERROR: current transaction is aborted, commands ignored until end of transaction block
|
||||
step c2: COMMIT;
|
||||
step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv();
|
||||
x| y| z
|
||||
--+--+---
|
||||
11|11|100
|
||||
(1 row)
|
||||
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
|
||||
starting permutation: s1 s2 update1 update2 c1 check2 c2 mv
|
||||
step s1: SELECT;
|
||||
step s2: SELECT;
|
||||
step update1: UPDATE a SET j = 11 WHERE i = 1;
|
||||
step update2: UPDATE b SET j = 111 WHERE i = 1;
|
||||
ERROR: could not obtain lock on materialized view "mv" during incremental maintenance
|
||||
step c1: COMMIT;
|
||||
step check2: SELECT check_mv();
|
||||
ERROR: current transaction is aborted, commands ignored until end of transaction block
|
||||
step c2: COMMIT;
|
||||
step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv();
|
||||
x| y| z
|
||||
--+--+---
|
||||
11|11|100
|
||||
(1 row)
|
||||
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
|
||||
starting permutation: s1 s2 update2 update1 c2 check1 c1 mv
|
||||
step s1: SELECT;
|
||||
step s2: SELECT;
|
||||
step update2: UPDATE b SET j = 111 WHERE i = 1;
|
||||
step update1: UPDATE a SET j = 11 WHERE i = 1;
|
||||
ERROR: could not obtain lock on materialized view "mv" during incremental maintenance
|
||||
step c2: COMMIT;
|
||||
step check1: SELECT check_mv();
|
||||
ERROR: current transaction is aborted, commands ignored until end of transaction block
|
||||
step c1: COMMIT;
|
||||
step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv();
|
||||
x| y| z
|
||||
--+--+---
|
||||
10|10|111
|
||||
(1 row)
|
||||
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
|
||||
starting permutation: s1 s2 update1 c1 update2 check2 c2 mv
|
||||
step s1: SELECT;
|
||||
step s2: SELECT;
|
||||
step update1: UPDATE a SET j = 11 WHERE i = 1;
|
||||
step c1: COMMIT;
|
||||
step update2: UPDATE b SET j = 111 WHERE i = 1;
|
||||
ERROR: the materialized view is incrementally updated in concurrent transaction
|
||||
step check2: SELECT check_mv();
|
||||
ERROR: current transaction is aborted, commands ignored until end of transaction block
|
||||
step c2: COMMIT;
|
||||
step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv();
|
||||
x| y| z
|
||||
--+--+---
|
||||
11|11|100
|
||||
(1 row)
|
||||
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
|
||||
starting permutation: s2 update2 s1 update1 c2 check1 c1 mv
|
||||
step s2: SELECT;
|
||||
step update2: UPDATE b SET j = 111 WHERE i = 1;
|
||||
step s1: SELECT;
|
||||
step update1: UPDATE a SET j = 11 WHERE i = 1;
|
||||
ERROR: could not obtain lock on materialized view "mv" during incremental maintenance
|
||||
step c2: COMMIT;
|
||||
step check1: SELECT check_mv();
|
||||
ERROR: current transaction is aborted, commands ignored until end of transaction block
|
||||
step c1: COMMIT;
|
||||
step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv();
|
||||
x| y| z
|
||||
--+--+---
|
||||
10|10|111
|
||||
(1 row)
|
||||
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
|
||||
starting permutation: s2 update2 s1 c2 update1 check1 c1 mv
|
||||
step s2: SELECT;
|
||||
step update2: UPDATE b SET j = 111 WHERE i = 1;
|
||||
step s1: SELECT;
|
||||
step c2: COMMIT;
|
||||
step update1: UPDATE a SET j = 11 WHERE i = 1;
|
||||
ERROR: the materialized view is incrementally updated in concurrent transaction
|
||||
step check1: SELECT check_mv();
|
||||
ERROR: current transaction is aborted, commands ignored until end of transaction block
|
||||
step c1: COMMIT;
|
||||
step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv();
|
||||
x| y| z
|
||||
--+--+---
|
||||
10|10|111
|
||||
(1 row)
|
||||
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
|
||||
starting permutation: s2 s1 update2 c2 update1 check1 c1 mv
|
||||
step s2: SELECT;
|
||||
step s1: SELECT;
|
||||
step update2: UPDATE b SET j = 111 WHERE i = 1;
|
||||
step c2: COMMIT;
|
||||
step update1: UPDATE a SET j = 11 WHERE i = 1;
|
||||
ERROR: the materialized view is incrementally updated in concurrent transaction
|
||||
step check1: SELECT check_mv();
|
||||
ERROR: current transaction is aborted, commands ignored until end of transaction block
|
||||
step c1: COMMIT;
|
||||
step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv();
|
||||
x| y| z
|
||||
--+--+---
|
||||
10|10|111
|
||||
(1 row)
|
||||
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
|
||||
starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv
|
||||
step s1: SELECT;
|
||||
step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200);
|
||||
step s2: SELECT;
|
||||
step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201);
|
||||
ERROR: could not obtain lock on materialized view "mv" during incremental maintenance
|
||||
step c1: COMMIT;
|
||||
step check2: SELECT check_mv();
|
||||
ERROR: current transaction is aborted, commands ignored until end of transaction block
|
||||
step c2: COMMIT;
|
||||
step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv();
|
||||
x| y| z
|
||||
--+--+---
|
||||
10|10|100
|
||||
20|20|200
|
||||
(2 rows)
|
||||
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
|
||||
starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv
|
||||
step s1: SELECT;
|
||||
step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200);
|
||||
step s2: SELECT;
|
||||
step c1: COMMIT;
|
||||
step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201);
|
||||
ERROR: the materialized view is incrementally updated in concurrent transaction
|
||||
step check2: SELECT check_mv();
|
||||
ERROR: current transaction is aborted, commands ignored until end of transaction block
|
||||
step c2: COMMIT;
|
||||
step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv();
|
||||
x| y| z
|
||||
--+--+---
|
||||
10|10|100
|
||||
20|20|200
|
||||
(2 rows)
|
||||
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
|
||||
starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv
|
||||
step s1: SELECT;
|
||||
step s2: SELECT;
|
||||
step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200);
|
||||
step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201);
|
||||
ERROR: could not obtain lock on materialized view "mv" during incremental maintenance
|
||||
step c1: COMMIT;
|
||||
step check2: SELECT check_mv();
|
||||
ERROR: current transaction is aborted, commands ignored until end of transaction block
|
||||
step c2: COMMIT;
|
||||
step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv();
|
||||
x| y| z
|
||||
--+--+---
|
||||
10|10|100
|
||||
20|20|200
|
||||
(2 rows)
|
||||
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
|
||||
starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv
|
||||
step s1: SELECT;
|
||||
step s2: SELECT;
|
||||
step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201);
|
||||
step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200);
|
||||
ERROR: could not obtain lock on materialized view "mv" during incremental maintenance
|
||||
step c2: COMMIT;
|
||||
step check1: SELECT check_mv();
|
||||
ERROR: current transaction is aborted, commands ignored until end of transaction block
|
||||
step c1: COMMIT;
|
||||
step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv();
|
||||
x| y| z
|
||||
--+--+---
|
||||
10|10|100
|
||||
10|11|100
|
||||
11|10|100
|
||||
11|11|100
|
||||
21|21|201
|
||||
(5 rows)
|
||||
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
|
||||
starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv
|
||||
step s1: SELECT;
|
||||
step s2: SELECT;
|
||||
step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200);
|
||||
step c1: COMMIT;
|
||||
step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201);
|
||||
ERROR: the materialized view is incrementally updated in concurrent transaction
|
||||
step check2: SELECT check_mv();
|
||||
ERROR: current transaction is aborted, commands ignored until end of transaction block
|
||||
step c2: COMMIT;
|
||||
step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv();
|
||||
x| y| z
|
||||
--+--+---
|
||||
10|10|100
|
||||
20|20|200
|
||||
(2 rows)
|
||||
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
|
||||
starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv
|
||||
step s2: SELECT;
|
||||
step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201);
|
||||
step s1: SELECT;
|
||||
step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200);
|
||||
ERROR: could not obtain lock on materialized view "mv" during incremental maintenance
|
||||
step c2: COMMIT;
|
||||
step check1: SELECT check_mv();
|
||||
ERROR: current transaction is aborted, commands ignored until end of transaction block
|
||||
step c1: COMMIT;
|
||||
step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv();
|
||||
x| y| z
|
||||
--+--+---
|
||||
10|10|100
|
||||
10|11|100
|
||||
11|10|100
|
||||
11|11|100
|
||||
21|21|201
|
||||
(5 rows)
|
||||
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
|
||||
starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv
|
||||
step s2: SELECT;
|
||||
step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201);
|
||||
step s1: SELECT;
|
||||
step c2: COMMIT;
|
||||
step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200);
|
||||
ERROR: the materialized view is incrementally updated in concurrent transaction
|
||||
step check1: SELECT check_mv();
|
||||
ERROR: current transaction is aborted, commands ignored until end of transaction block
|
||||
step c1: COMMIT;
|
||||
step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv();
|
||||
x| y| z
|
||||
--+--+---
|
||||
10|10|100
|
||||
10|11|100
|
||||
11|10|100
|
||||
11|11|100
|
||||
21|21|201
|
||||
(5 rows)
|
||||
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
|
||||
starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv
|
||||
step s2: SELECT;
|
||||
step s1: SELECT;
|
||||
step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201);
|
||||
step c2: COMMIT;
|
||||
step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200);
|
||||
ERROR: the materialized view is incrementally updated in concurrent transaction
|
||||
step check1: SELECT check_mv();
|
||||
ERROR: current transaction is aborted, commands ignored until end of transaction block
|
||||
step c1: COMMIT;
|
||||
step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv();
|
||||
x| y| z
|
||||
--+--+---
|
||||
10|10|100
|
||||
10|11|100
|
||||
11|10|100
|
||||
11|11|100
|
||||
21|21|201
|
||||
(5 rows)
|
||||
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
373
expected/insert_insert3.out
Normal file
373
expected/insert_insert3.out
Normal file
|
|
@ -0,0 +1,373 @@
|
|||
Parsed test spec with 2 sessions
|
||||
|
||||
starting permutation: s1 update1 s2 update2 c1 check2 c2 mv
|
||||
step s1: SELECT;
|
||||
step update1: UPDATE a SET j = 11 WHERE i = 1;
|
||||
step s2: SELECT;
|
||||
step update2: UPDATE b SET j = 111 WHERE i = 1;
|
||||
ERROR: could not obtain lock on materialized view "mv" during incremental maintenance
|
||||
step c1: COMMIT;
|
||||
step check2: SELECT check_mv();
|
||||
ERROR: current transaction is aborted, commands ignored until end of transaction block
|
||||
step c2: COMMIT;
|
||||
step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv();
|
||||
x| y| z
|
||||
--+--+---
|
||||
11|11|100
|
||||
(1 row)
|
||||
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
|
||||
starting permutation: s1 update1 s2 c1 update2 check2 c2 mv
|
||||
step s1: SELECT;
|
||||
step update1: UPDATE a SET j = 11 WHERE i = 1;
|
||||
step s2: SELECT;
|
||||
step c1: COMMIT;
|
||||
step update2: UPDATE b SET j = 111 WHERE i = 1;
|
||||
ERROR: the materialized view is incrementally updated in concurrent transaction
|
||||
step check2: SELECT check_mv();
|
||||
ERROR: current transaction is aborted, commands ignored until end of transaction block
|
||||
step c2: COMMIT;
|
||||
step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv();
|
||||
x| y| z
|
||||
--+--+---
|
||||
11|11|100
|
||||
(1 row)
|
||||
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
|
||||
starting permutation: s1 s2 update1 update2 c1 check2 c2 mv
|
||||
step s1: SELECT;
|
||||
step s2: SELECT;
|
||||
step update1: UPDATE a SET j = 11 WHERE i = 1;
|
||||
step update2: UPDATE b SET j = 111 WHERE i = 1;
|
||||
ERROR: could not obtain lock on materialized view "mv" during incremental maintenance
|
||||
step c1: COMMIT;
|
||||
step check2: SELECT check_mv();
|
||||
ERROR: current transaction is aborted, commands ignored until end of transaction block
|
||||
step c2: COMMIT;
|
||||
step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv();
|
||||
x| y| z
|
||||
--+--+---
|
||||
11|11|100
|
||||
(1 row)
|
||||
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
|
||||
starting permutation: s1 s2 update2 update1 c2 check1 c1 mv
|
||||
step s1: SELECT;
|
||||
step s2: SELECT;
|
||||
step update2: UPDATE b SET j = 111 WHERE i = 1;
|
||||
step update1: UPDATE a SET j = 11 WHERE i = 1;
|
||||
ERROR: could not obtain lock on materialized view "mv" during incremental maintenance
|
||||
step c2: COMMIT;
|
||||
step check1: SELECT check_mv();
|
||||
ERROR: current transaction is aborted, commands ignored until end of transaction block
|
||||
step c1: COMMIT;
|
||||
step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv();
|
||||
x| y| z
|
||||
--+--+---
|
||||
10|10|111
|
||||
(1 row)
|
||||
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
|
||||
starting permutation: s1 s2 update1 c1 update2 check2 c2 mv
|
||||
step s1: SELECT;
|
||||
step s2: SELECT;
|
||||
step update1: UPDATE a SET j = 11 WHERE i = 1;
|
||||
step c1: COMMIT;
|
||||
step update2: UPDATE b SET j = 111 WHERE i = 1;
|
||||
ERROR: the materialized view is incrementally updated in concurrent transaction
|
||||
step check2: SELECT check_mv();
|
||||
ERROR: current transaction is aborted, commands ignored until end of transaction block
|
||||
step c2: COMMIT;
|
||||
step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv();
|
||||
x| y| z
|
||||
--+--+---
|
||||
11|11|100
|
||||
(1 row)
|
||||
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
|
||||
starting permutation: s2 update2 s1 update1 c2 check1 c1 mv
|
||||
step s2: SELECT;
|
||||
step update2: UPDATE b SET j = 111 WHERE i = 1;
|
||||
step s1: SELECT;
|
||||
step update1: UPDATE a SET j = 11 WHERE i = 1;
|
||||
ERROR: could not obtain lock on materialized view "mv" during incremental maintenance
|
||||
step c2: COMMIT;
|
||||
step check1: SELECT check_mv();
|
||||
ERROR: current transaction is aborted, commands ignored until end of transaction block
|
||||
step c1: COMMIT;
|
||||
step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv();
|
||||
x| y| z
|
||||
--+--+---
|
||||
10|10|111
|
||||
(1 row)
|
||||
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
|
||||
starting permutation: s2 update2 s1 c2 update1 check1 c1 mv
|
||||
step s2: SELECT;
|
||||
step update2: UPDATE b SET j = 111 WHERE i = 1;
|
||||
step s1: SELECT;
|
||||
step c2: COMMIT;
|
||||
step update1: UPDATE a SET j = 11 WHERE i = 1;
|
||||
ERROR: the materialized view is incrementally updated in concurrent transaction
|
||||
step check1: SELECT check_mv();
|
||||
ERROR: current transaction is aborted, commands ignored until end of transaction block
|
||||
step c1: COMMIT;
|
||||
step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv();
|
||||
x| y| z
|
||||
--+--+---
|
||||
10|10|111
|
||||
(1 row)
|
||||
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
|
||||
starting permutation: s2 s1 update2 c2 update1 check1 c1 mv
|
||||
step s2: SELECT;
|
||||
step s1: SELECT;
|
||||
step update2: UPDATE b SET j = 111 WHERE i = 1;
|
||||
step c2: COMMIT;
|
||||
step update1: UPDATE a SET j = 11 WHERE i = 1;
|
||||
ERROR: the materialized view is incrementally updated in concurrent transaction
|
||||
step check1: SELECT check_mv();
|
||||
ERROR: current transaction is aborted, commands ignored until end of transaction block
|
||||
step c1: COMMIT;
|
||||
step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv();
|
||||
x| y| z
|
||||
--+--+---
|
||||
10|10|111
|
||||
(1 row)
|
||||
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
|
||||
starting permutation: s1 insert1 s2 insert2 c1 check2 c2 mv
|
||||
step s1: SELECT;
|
||||
step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200);
|
||||
step s2: SELECT;
|
||||
step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201);
|
||||
ERROR: could not obtain lock on materialized view "mv" during incremental maintenance
|
||||
step c1: COMMIT;
|
||||
step check2: SELECT check_mv();
|
||||
ERROR: current transaction is aborted, commands ignored until end of transaction block
|
||||
step c2: COMMIT;
|
||||
step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv();
|
||||
x| y| z
|
||||
--+--+---
|
||||
10|10|100
|
||||
20|20|200
|
||||
(2 rows)
|
||||
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
|
||||
starting permutation: s1 insert1 s2 c1 insert2 check2 c2 mv
|
||||
step s1: SELECT;
|
||||
step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200);
|
||||
step s2: SELECT;
|
||||
step c1: COMMIT;
|
||||
step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201);
|
||||
ERROR: the materialized view is incrementally updated in concurrent transaction
|
||||
step check2: SELECT check_mv();
|
||||
ERROR: current transaction is aborted, commands ignored until end of transaction block
|
||||
step c2: COMMIT;
|
||||
step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv();
|
||||
x| y| z
|
||||
--+--+---
|
||||
10|10|100
|
||||
20|20|200
|
||||
(2 rows)
|
||||
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
|
||||
starting permutation: s1 s2 insert1 insert2 c1 check2 c2 mv
|
||||
step s1: SELECT;
|
||||
step s2: SELECT;
|
||||
step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200);
|
||||
step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201);
|
||||
ERROR: could not obtain lock on materialized view "mv" during incremental maintenance
|
||||
step c1: COMMIT;
|
||||
step check2: SELECT check_mv();
|
||||
ERROR: current transaction is aborted, commands ignored until end of transaction block
|
||||
step c2: COMMIT;
|
||||
step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv();
|
||||
x| y| z
|
||||
--+--+---
|
||||
10|10|100
|
||||
20|20|200
|
||||
(2 rows)
|
||||
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
|
||||
starting permutation: s1 s2 insert2 insert1 c2 check1 c1 mv
|
||||
step s1: SELECT;
|
||||
step s2: SELECT;
|
||||
step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201);
|
||||
step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200);
|
||||
ERROR: could not obtain lock on materialized view "mv" during incremental maintenance
|
||||
step c2: COMMIT;
|
||||
step check1: SELECT check_mv();
|
||||
ERROR: current transaction is aborted, commands ignored until end of transaction block
|
||||
step c1: COMMIT;
|
||||
step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv();
|
||||
x| y| z
|
||||
--+--+---
|
||||
10|10|100
|
||||
10|11|100
|
||||
11|10|100
|
||||
11|11|100
|
||||
21|21|201
|
||||
(5 rows)
|
||||
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
|
||||
starting permutation: s1 s2 insert1 c1 insert2 check2 c2 mv
|
||||
step s1: SELECT;
|
||||
step s2: SELECT;
|
||||
step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200);
|
||||
step c1: COMMIT;
|
||||
step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201);
|
||||
ERROR: the materialized view is incrementally updated in concurrent transaction
|
||||
step check2: SELECT check_mv();
|
||||
ERROR: current transaction is aborted, commands ignored until end of transaction block
|
||||
step c2: COMMIT;
|
||||
step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv();
|
||||
x| y| z
|
||||
--+--+---
|
||||
10|10|100
|
||||
20|20|200
|
||||
(2 rows)
|
||||
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
|
||||
starting permutation: s2 insert2 s1 insert1 c2 check1 c1 mv
|
||||
step s2: SELECT;
|
||||
step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201);
|
||||
step s1: SELECT;
|
||||
step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200);
|
||||
ERROR: could not obtain lock on materialized view "mv" during incremental maintenance
|
||||
step c2: COMMIT;
|
||||
step check1: SELECT check_mv();
|
||||
ERROR: current transaction is aborted, commands ignored until end of transaction block
|
||||
step c1: COMMIT;
|
||||
step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv();
|
||||
x| y| z
|
||||
--+--+---
|
||||
10|10|100
|
||||
10|11|100
|
||||
11|10|100
|
||||
11|11|100
|
||||
21|21|201
|
||||
(5 rows)
|
||||
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
|
||||
starting permutation: s2 insert2 s1 c2 insert1 check1 c1 mv
|
||||
step s2: SELECT;
|
||||
step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201);
|
||||
step s1: SELECT;
|
||||
step c2: COMMIT;
|
||||
step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200);
|
||||
ERROR: the materialized view is incrementally updated in concurrent transaction
|
||||
step check1: SELECT check_mv();
|
||||
ERROR: current transaction is aborted, commands ignored until end of transaction block
|
||||
step c1: COMMIT;
|
||||
step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv();
|
||||
x| y| z
|
||||
--+--+---
|
||||
10|10|100
|
||||
10|11|100
|
||||
11|10|100
|
||||
11|11|100
|
||||
21|21|201
|
||||
(5 rows)
|
||||
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
|
||||
starting permutation: s2 s1 insert2 c2 insert1 check1 c1 mv
|
||||
step s2: SELECT;
|
||||
step s1: SELECT;
|
||||
step insert2: INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201);
|
||||
step c2: COMMIT;
|
||||
step insert1: INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200);
|
||||
ERROR: the materialized view is incrementally updated in concurrent transaction
|
||||
step check1: SELECT check_mv();
|
||||
ERROR: current transaction is aborted, commands ignored until end of transaction block
|
||||
step c1: COMMIT;
|
||||
step mv: SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv();
|
||||
x| y| z
|
||||
--+--+---
|
||||
10|10|100
|
||||
10|11|100
|
||||
11|10|100
|
||||
11|11|100
|
||||
21|21|201
|
||||
(5 rows)
|
||||
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
253
expected/refresh_insert.out
Normal file
253
expected/refresh_insert.out
Normal file
|
|
@ -0,0 +1,253 @@
|
|||
Parsed test spec with 2 sessions
|
||||
|
||||
starting permutation: s1 refresh s2 insert c1 check2 c2 mv
|
||||
step s1: SELECT;
|
||||
step refresh: SELECT pgivm.refresh_immv('mv', true);
|
||||
refresh_immv
|
||||
------------
|
||||
1
|
||||
(1 row)
|
||||
|
||||
step s2: SELECT;
|
||||
step insert: INSERT INTO a VALUES (2); <waiting ...>
|
||||
step c1: COMMIT;
|
||||
step insert: <... completed>
|
||||
step check2: SELECT check_mv();
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
step c2: COMMIT;
|
||||
step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv();
|
||||
x|y
|
||||
-+-
|
||||
1|1
|
||||
2|2
|
||||
(2 rows)
|
||||
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
|
||||
starting permutation: s1 refresh s2 c1 insert check2 c2 mv
|
||||
step s1: SELECT;
|
||||
step refresh: SELECT pgivm.refresh_immv('mv', true);
|
||||
refresh_immv
|
||||
------------
|
||||
1
|
||||
(1 row)
|
||||
|
||||
step s2: SELECT;
|
||||
step c1: COMMIT;
|
||||
step insert: INSERT INTO a VALUES (2);
|
||||
step check2: SELECT check_mv();
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
step c2: COMMIT;
|
||||
step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv();
|
||||
x|y
|
||||
-+-
|
||||
1|1
|
||||
2|2
|
||||
(2 rows)
|
||||
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
|
||||
starting permutation: s1 s2 refresh insert c1 check2 c2 mv
|
||||
step s1: SELECT;
|
||||
step s2: SELECT;
|
||||
step refresh: SELECT pgivm.refresh_immv('mv', true);
|
||||
refresh_immv
|
||||
------------
|
||||
1
|
||||
(1 row)
|
||||
|
||||
step insert: INSERT INTO a VALUES (2); <waiting ...>
|
||||
step c1: COMMIT;
|
||||
step insert: <... completed>
|
||||
step check2: SELECT check_mv();
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
step c2: COMMIT;
|
||||
step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv();
|
||||
x|y
|
||||
-+-
|
||||
1|1
|
||||
2|2
|
||||
(2 rows)
|
||||
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
|
||||
starting permutation: s1 s2 insert refresh c2 check1 c1 mv
|
||||
step s1: SELECT;
|
||||
step s2: SELECT;
|
||||
step insert: INSERT INTO a VALUES (2);
|
||||
step refresh: SELECT pgivm.refresh_immv('mv', true); <waiting ...>
|
||||
step c2: COMMIT;
|
||||
step refresh: <... completed>
|
||||
refresh_immv
|
||||
------------
|
||||
2
|
||||
(1 row)
|
||||
|
||||
step check1: SELECT check_mv();
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
step c1: COMMIT;
|
||||
step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv();
|
||||
x|y
|
||||
-+-
|
||||
1|1
|
||||
2|2
|
||||
(2 rows)
|
||||
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
|
||||
starting permutation: s1 s2 refresh c1 insert check2 c2 mv
|
||||
step s1: SELECT;
|
||||
step s2: SELECT;
|
||||
step refresh: SELECT pgivm.refresh_immv('mv', true);
|
||||
refresh_immv
|
||||
------------
|
||||
1
|
||||
(1 row)
|
||||
|
||||
step c1: COMMIT;
|
||||
step insert: INSERT INTO a VALUES (2);
|
||||
step check2: SELECT check_mv();
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
step c2: COMMIT;
|
||||
step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv();
|
||||
x|y
|
||||
-+-
|
||||
1|1
|
||||
2|2
|
||||
(2 rows)
|
||||
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
|
||||
starting permutation: s2 insert s1 refresh c2 check1 c1 mv
|
||||
step s2: SELECT;
|
||||
step insert: INSERT INTO a VALUES (2);
|
||||
step s1: SELECT;
|
||||
step refresh: SELECT pgivm.refresh_immv('mv', true); <waiting ...>
|
||||
step c2: COMMIT;
|
||||
step refresh: <... completed>
|
||||
refresh_immv
|
||||
------------
|
||||
2
|
||||
(1 row)
|
||||
|
||||
step check1: SELECT check_mv();
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
step c1: COMMIT;
|
||||
step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv();
|
||||
x|y
|
||||
-+-
|
||||
1|1
|
||||
2|2
|
||||
(2 rows)
|
||||
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
|
||||
starting permutation: s2 insert s1 c2 refresh check1 c1 mv
|
||||
step s2: SELECT;
|
||||
step insert: INSERT INTO a VALUES (2);
|
||||
step s1: SELECT;
|
||||
step c2: COMMIT;
|
||||
step refresh: SELECT pgivm.refresh_immv('mv', true);
|
||||
refresh_immv
|
||||
------------
|
||||
2
|
||||
(1 row)
|
||||
|
||||
step check1: SELECT check_mv();
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
step c1: COMMIT;
|
||||
step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv();
|
||||
x|y
|
||||
-+-
|
||||
1|1
|
||||
2|2
|
||||
(2 rows)
|
||||
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
|
||||
starting permutation: s2 s1 insert c2 refresh check1 c1 mv
|
||||
step s2: SELECT;
|
||||
step s1: SELECT;
|
||||
step insert: INSERT INTO a VALUES (2);
|
||||
step c2: COMMIT;
|
||||
step refresh: SELECT pgivm.refresh_immv('mv', true);
|
||||
refresh_immv
|
||||
------------
|
||||
2
|
||||
(1 row)
|
||||
|
||||
step check1: SELECT check_mv();
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
step c1: COMMIT;
|
||||
step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv();
|
||||
x|y
|
||||
-+-
|
||||
1|1
|
||||
2|2
|
||||
(2 rows)
|
||||
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
211
expected/refresh_insert2.out
Normal file
211
expected/refresh_insert2.out
Normal file
|
|
@ -0,0 +1,211 @@
|
|||
Parsed test spec with 2 sessions
|
||||
|
||||
starting permutation: s1 refresh s2 insert c1 check2 c2 mv
|
||||
step s1: SELECT;
|
||||
step refresh: SELECT pgivm.refresh_immv('mv', true);
|
||||
refresh_immv
|
||||
------------
|
||||
1
|
||||
(1 row)
|
||||
|
||||
step s2: SELECT;
|
||||
step insert: INSERT INTO a VALUES (2);
|
||||
ERROR: could not obtain lock on materialized view "mv" during incremental maintenance
|
||||
step c1: COMMIT;
|
||||
step check2: SELECT check_mv();
|
||||
ERROR: current transaction is aborted, commands ignored until end of transaction block
|
||||
step c2: COMMIT;
|
||||
step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv();
|
||||
x|y
|
||||
-+-
|
||||
1|1
|
||||
(1 row)
|
||||
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
|
||||
starting permutation: s1 refresh s2 c1 insert check2 c2 mv
|
||||
step s1: SELECT;
|
||||
step refresh: SELECT pgivm.refresh_immv('mv', true);
|
||||
refresh_immv
|
||||
------------
|
||||
1
|
||||
(1 row)
|
||||
|
||||
step s2: SELECT;
|
||||
step c1: COMMIT;
|
||||
step insert: INSERT INTO a VALUES (2);
|
||||
step check2: SELECT check_mv();
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
step c2: COMMIT;
|
||||
step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv();
|
||||
x|y
|
||||
-+-
|
||||
1|1
|
||||
2|2
|
||||
(2 rows)
|
||||
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
|
||||
starting permutation: s1 s2 refresh insert c1 check2 c2 mv
|
||||
step s1: SELECT;
|
||||
step s2: SELECT;
|
||||
step refresh: SELECT pgivm.refresh_immv('mv', true);
|
||||
refresh_immv
|
||||
------------
|
||||
1
|
||||
(1 row)
|
||||
|
||||
step insert: INSERT INTO a VALUES (2);
|
||||
ERROR: could not obtain lock on materialized view "mv" during incremental maintenance
|
||||
step c1: COMMIT;
|
||||
step check2: SELECT check_mv();
|
||||
ERROR: current transaction is aborted, commands ignored until end of transaction block
|
||||
step c2: COMMIT;
|
||||
step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv();
|
||||
x|y
|
||||
-+-
|
||||
1|1
|
||||
(1 row)
|
||||
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
|
||||
starting permutation: s1 s2 insert refresh c2 check1 c1 mv
|
||||
step s1: SELECT;
|
||||
step s2: SELECT;
|
||||
step insert: INSERT INTO a VALUES (2);
|
||||
step refresh: SELECT pgivm.refresh_immv('mv', true); <waiting ...>
|
||||
step c2: COMMIT;
|
||||
step refresh: <... completed>
|
||||
ERROR: the materialized view is incrementally updated in concurrent transaction
|
||||
step check1: SELECT check_mv();
|
||||
ERROR: current transaction is aborted, commands ignored until end of transaction block
|
||||
step c1: COMMIT;
|
||||
step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv();
|
||||
x|y
|
||||
-+-
|
||||
1|1
|
||||
2|2
|
||||
(2 rows)
|
||||
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
|
||||
starting permutation: s1 s2 refresh c1 insert check2 c2 mv
|
||||
step s1: SELECT;
|
||||
step s2: SELECT;
|
||||
step refresh: SELECT pgivm.refresh_immv('mv', true);
|
||||
refresh_immv
|
||||
------------
|
||||
1
|
||||
(1 row)
|
||||
|
||||
step c1: COMMIT;
|
||||
step insert: INSERT INTO a VALUES (2);
|
||||
step check2: SELECT check_mv();
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
step c2: COMMIT;
|
||||
step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv();
|
||||
x|y
|
||||
-+-
|
||||
1|1
|
||||
2|2
|
||||
(2 rows)
|
||||
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
|
||||
starting permutation: s2 insert s1 refresh c2 check1 c1 mv
|
||||
step s2: SELECT;
|
||||
step insert: INSERT INTO a VALUES (2);
|
||||
step s1: SELECT;
|
||||
step refresh: SELECT pgivm.refresh_immv('mv', true); <waiting ...>
|
||||
step c2: COMMIT;
|
||||
step refresh: <... completed>
|
||||
ERROR: the materialized view is incrementally updated in concurrent transaction
|
||||
step check1: SELECT check_mv();
|
||||
ERROR: current transaction is aborted, commands ignored until end of transaction block
|
||||
step c1: COMMIT;
|
||||
step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv();
|
||||
x|y
|
||||
-+-
|
||||
1|1
|
||||
2|2
|
||||
(2 rows)
|
||||
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
|
||||
starting permutation: s2 insert s1 c2 refresh check1 c1 mv
|
||||
step s2: SELECT;
|
||||
step insert: INSERT INTO a VALUES (2);
|
||||
step s1: SELECT;
|
||||
step c2: COMMIT;
|
||||
step refresh: SELECT pgivm.refresh_immv('mv', true);
|
||||
ERROR: the materialized view is incrementally updated in concurrent transaction
|
||||
step check1: SELECT check_mv();
|
||||
ERROR: current transaction is aborted, commands ignored until end of transaction block
|
||||
step c1: COMMIT;
|
||||
step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv();
|
||||
x|y
|
||||
-+-
|
||||
1|1
|
||||
2|2
|
||||
(2 rows)
|
||||
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
|
||||
starting permutation: s2 s1 insert c2 refresh check1 c1 mv
|
||||
step s2: SELECT;
|
||||
step s1: SELECT;
|
||||
step insert: INSERT INTO a VALUES (2);
|
||||
step c2: COMMIT;
|
||||
step refresh: SELECT pgivm.refresh_immv('mv', true);
|
||||
ERROR: the materialized view is incrementally updated in concurrent transaction
|
||||
step check1: SELECT check_mv();
|
||||
ERROR: current transaction is aborted, commands ignored until end of transaction block
|
||||
step c1: COMMIT;
|
||||
step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv();
|
||||
x|y
|
||||
-+-
|
||||
1|1
|
||||
2|2
|
||||
(2 rows)
|
||||
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
211
expected/refresh_insert3.out
Normal file
211
expected/refresh_insert3.out
Normal file
|
|
@ -0,0 +1,211 @@
|
|||
Parsed test spec with 2 sessions
|
||||
|
||||
starting permutation: s1 refresh s2 insert c1 check2 c2 mv
|
||||
step s1: SELECT;
|
||||
step refresh: SELECT pgivm.refresh_immv('mv', true);
|
||||
refresh_immv
|
||||
------------
|
||||
1
|
||||
(1 row)
|
||||
|
||||
step s2: SELECT;
|
||||
step insert: INSERT INTO a VALUES (2);
|
||||
ERROR: could not obtain lock on materialized view "mv" during incremental maintenance
|
||||
step c1: COMMIT;
|
||||
step check2: SELECT check_mv();
|
||||
ERROR: current transaction is aborted, commands ignored until end of transaction block
|
||||
step c2: COMMIT;
|
||||
step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv();
|
||||
x|y
|
||||
-+-
|
||||
1|1
|
||||
(1 row)
|
||||
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
|
||||
starting permutation: s1 refresh s2 c1 insert check2 c2 mv
|
||||
step s1: SELECT;
|
||||
step refresh: SELECT pgivm.refresh_immv('mv', true);
|
||||
refresh_immv
|
||||
------------
|
||||
1
|
||||
(1 row)
|
||||
|
||||
step s2: SELECT;
|
||||
step c1: COMMIT;
|
||||
step insert: INSERT INTO a VALUES (2);
|
||||
step check2: SELECT check_mv();
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
step c2: COMMIT;
|
||||
step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv();
|
||||
x|y
|
||||
-+-
|
||||
1|1
|
||||
2|2
|
||||
(2 rows)
|
||||
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
|
||||
starting permutation: s1 s2 refresh insert c1 check2 c2 mv
|
||||
step s1: SELECT;
|
||||
step s2: SELECT;
|
||||
step refresh: SELECT pgivm.refresh_immv('mv', true);
|
||||
refresh_immv
|
||||
------------
|
||||
1
|
||||
(1 row)
|
||||
|
||||
step insert: INSERT INTO a VALUES (2);
|
||||
ERROR: could not obtain lock on materialized view "mv" during incremental maintenance
|
||||
step c1: COMMIT;
|
||||
step check2: SELECT check_mv();
|
||||
ERROR: current transaction is aborted, commands ignored until end of transaction block
|
||||
step c2: COMMIT;
|
||||
step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv();
|
||||
x|y
|
||||
-+-
|
||||
1|1
|
||||
(1 row)
|
||||
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
|
||||
starting permutation: s1 s2 insert refresh c2 check1 c1 mv
|
||||
step s1: SELECT;
|
||||
step s2: SELECT;
|
||||
step insert: INSERT INTO a VALUES (2);
|
||||
step refresh: SELECT pgivm.refresh_immv('mv', true); <waiting ...>
|
||||
step c2: COMMIT;
|
||||
step refresh: <... completed>
|
||||
ERROR: the materialized view is incrementally updated in concurrent transaction
|
||||
step check1: SELECT check_mv();
|
||||
ERROR: current transaction is aborted, commands ignored until end of transaction block
|
||||
step c1: COMMIT;
|
||||
step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv();
|
||||
x|y
|
||||
-+-
|
||||
1|1
|
||||
2|2
|
||||
(2 rows)
|
||||
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
|
||||
starting permutation: s1 s2 refresh c1 insert check2 c2 mv
|
||||
step s1: SELECT;
|
||||
step s2: SELECT;
|
||||
step refresh: SELECT pgivm.refresh_immv('mv', true);
|
||||
refresh_immv
|
||||
------------
|
||||
1
|
||||
(1 row)
|
||||
|
||||
step c1: COMMIT;
|
||||
step insert: INSERT INTO a VALUES (2);
|
||||
step check2: SELECT check_mv();
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
step c2: COMMIT;
|
||||
step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv();
|
||||
x|y
|
||||
-+-
|
||||
1|1
|
||||
2|2
|
||||
(2 rows)
|
||||
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
|
||||
starting permutation: s2 insert s1 refresh c2 check1 c1 mv
|
||||
step s2: SELECT;
|
||||
step insert: INSERT INTO a VALUES (2);
|
||||
step s1: SELECT;
|
||||
step refresh: SELECT pgivm.refresh_immv('mv', true); <waiting ...>
|
||||
step c2: COMMIT;
|
||||
step refresh: <... completed>
|
||||
ERROR: the materialized view is incrementally updated in concurrent transaction
|
||||
step check1: SELECT check_mv();
|
||||
ERROR: current transaction is aborted, commands ignored until end of transaction block
|
||||
step c1: COMMIT;
|
||||
step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv();
|
||||
x|y
|
||||
-+-
|
||||
1|1
|
||||
2|2
|
||||
(2 rows)
|
||||
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
|
||||
starting permutation: s2 insert s1 c2 refresh check1 c1 mv
|
||||
step s2: SELECT;
|
||||
step insert: INSERT INTO a VALUES (2);
|
||||
step s1: SELECT;
|
||||
step c2: COMMIT;
|
||||
step refresh: SELECT pgivm.refresh_immv('mv', true);
|
||||
ERROR: the materialized view is incrementally updated in concurrent transaction
|
||||
step check1: SELECT check_mv();
|
||||
ERROR: current transaction is aborted, commands ignored until end of transaction block
|
||||
step c1: COMMIT;
|
||||
step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv();
|
||||
x|y
|
||||
-+-
|
||||
1|1
|
||||
2|2
|
||||
(2 rows)
|
||||
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
|
||||
starting permutation: s2 s1 insert c2 refresh check1 c1 mv
|
||||
step s2: SELECT;
|
||||
step s1: SELECT;
|
||||
step insert: INSERT INTO a VALUES (2);
|
||||
step c2: COMMIT;
|
||||
step refresh: SELECT pgivm.refresh_immv('mv', true);
|
||||
ERROR: the materialized view is incrementally updated in concurrent transaction
|
||||
step check1: SELECT check_mv();
|
||||
ERROR: current transaction is aborted, commands ignored until end of transaction block
|
||||
step c1: COMMIT;
|
||||
step mv: SELECT * FROM mv ORDER BY 1,2; SELECT check_mv();
|
||||
x|y
|
||||
-+-
|
||||
1|1
|
||||
2|2
|
||||
(2 rows)
|
||||
|
||||
check_mv
|
||||
--------
|
||||
ok
|
||||
(1 row)
|
||||
|
||||
321
matview.c
321
matview.c
|
|
@ -50,6 +50,7 @@
|
|||
#include "utils/rel.h"
|
||||
#include "utils/snapmgr.h"
|
||||
#include "utils/typcache.h"
|
||||
#include "utils/xid8.h"
|
||||
|
||||
#include "pg_ivm.h"
|
||||
|
||||
|
|
@ -107,6 +108,15 @@ typedef struct MV_TriggerHashEntry
|
|||
List *tables; /* List of MV_TriggerTable */
|
||||
bool has_old; /* tuples are deleted from any table? */
|
||||
bool has_new; /* tuples are inserted into any table? */
|
||||
|
||||
/*
|
||||
* List of sub-transaction IDs that incrementally updated the view.
|
||||
* This list is maintained through a transaction, and an ID is removed
|
||||
* when a sub-transaction is aborted. If any ID is left when the
|
||||
* transaction is committed, this means the view is incrementally
|
||||
* updated in this transaction.
|
||||
*/
|
||||
List *subxids;
|
||||
} MV_TriggerHashEntry;
|
||||
|
||||
/*
|
||||
|
|
@ -218,7 +228,11 @@ static void mv_InitHashTables(void);
|
|||
static SPIPlanPtr mv_FetchPreparedPlan(MV_QueryKey *key);
|
||||
static void mv_HashPreparedPlan(MV_QueryKey *key, SPIPlanPtr plan);
|
||||
static void mv_BuildQueryKey(MV_QueryKey *key, Oid matview_id, int32 query_type);
|
||||
static void clean_up_IVM_hash_entry(MV_TriggerHashEntry *entry, bool is_abort);
|
||||
static void clean_up_IVM_hash_entry(MV_TriggerHashEntry *entry, bool is_abort,
|
||||
SubTransactionId subxid);
|
||||
static void setLastUpdateXid(Oid immv_oid, FullTransactionId xid);
|
||||
static FullTransactionId getLastUpdateXid(Oid immv_oid);
|
||||
|
||||
|
||||
/* SQL callable functions */
|
||||
PG_FUNCTION_INFO_V1(IVM_immediate_before);
|
||||
|
|
@ -257,16 +271,18 @@ ExecRefreshImmv(const RangeVar *relation, bool skipData,
|
|||
NULL);
|
||||
#endif
|
||||
|
||||
return RefreshImmvByOid(matviewOid, skipData, queryString, qc);
|
||||
return RefreshImmvByOid(matviewOid, false, skipData, queryString, qc);
|
||||
}
|
||||
|
||||
/*
|
||||
* RefreshMatViewByOid -- refresh IMMV view by OID
|
||||
*
|
||||
* This is also used to populate the IMMV created by create_immv command.
|
||||
*
|
||||
* This imitates PostgreSQL's RefreshMatViewByOid().
|
||||
*/
|
||||
ObjectAddress
|
||||
RefreshImmvByOid(Oid matviewOid, bool skipData,
|
||||
RefreshImmvByOid(Oid matviewOid, bool is_create, bool skipData,
|
||||
const char *queryString, QueryCompletion *qc)
|
||||
{
|
||||
Relation matviewRel;
|
||||
|
|
@ -446,6 +462,19 @@ RefreshImmvByOid(Oid matviewOid, bool skipData,
|
|||
free_object_addresses(immv_triggers);
|
||||
}
|
||||
|
||||
/*
|
||||
* Create triggers on incremental maintainable materialized view
|
||||
* This argument should use 'dataQuery'. This needs to use a rewritten query,
|
||||
* because a sublink in jointree is not supported by this function.
|
||||
*
|
||||
* This is performed before generating data because we have to wait
|
||||
* concurrent transactions modifying a base table and then take a snapshot
|
||||
* to see changes by these transactions to make sure a consistent view
|
||||
* is created.
|
||||
*/
|
||||
if (!skipData && !oldPopulated)
|
||||
CreateIvmTriggersOnBaseTables(dataQuery, matviewOid);
|
||||
|
||||
/*
|
||||
* Create the transient table that will receive the regenerated data. Lock
|
||||
* it against access by any other process until commit (by which time it
|
||||
|
|
@ -461,10 +490,41 @@ RefreshImmvByOid(Oid matviewOid, bool skipData,
|
|||
LockRelationOid(OIDNewHeap, AccessExclusiveLock);
|
||||
dest = CreateTransientRelDestReceiver(OIDNewHeap);
|
||||
|
||||
/*
|
||||
* In READ COMMITTED, get and push the latest snapshot again to see the
|
||||
* results of concurrent transactions committed after the current
|
||||
* transaction started.
|
||||
*/
|
||||
if (!IsolationUsesXactSnapshot())
|
||||
PushActiveSnapshot(GetTransactionSnapshot());
|
||||
|
||||
/*
|
||||
* If a concurrent transaction updated the view incrementally and was
|
||||
* committed before we acquired the lock, the results of refresh_immv could
|
||||
* be inconsistent. Therefore, we have to check the transaction ID of the
|
||||
* most recent update of the view, and if this was in progress at the
|
||||
* transaction start, raise an error to prevent anomalies.
|
||||
*/
|
||||
if (!is_create)
|
||||
{
|
||||
FullTransactionId xid;
|
||||
|
||||
xid = getLastUpdateXid(matviewOid);
|
||||
if (XidInMVCCSnapshot(XidFromFullTransactionId(xid), GetActiveSnapshot()))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
|
||||
errmsg("the materialized view is incrementally updated in concurrent transaction"),
|
||||
errhint("The transaction might succeed if retried.")));
|
||||
}
|
||||
|
||||
/* Generate the data, if wanted. */
|
||||
if (!skipData)
|
||||
processed = refresh_immv_datafill(dest, dataQuery, NULL, NULL, queryString);
|
||||
|
||||
/* Pop the original snapshot. */
|
||||
if (!IsolationUsesXactSnapshot())
|
||||
PopActiveSnapshot();
|
||||
|
||||
/* Make the matview match the newly generated data. */
|
||||
refresh_by_heap_swap(matviewOid, OIDNewHeap, relpersistence);
|
||||
|
||||
|
|
@ -478,14 +538,6 @@ RefreshImmvByOid(Oid matviewOid, bool skipData,
|
|||
if (!skipData)
|
||||
pgstat_count_heap_insert(matviewRel, processed);
|
||||
|
||||
/*
|
||||
* Create triggers on incremental maintainable materialized view
|
||||
* This argument should use 'dataQuery'. This needs to use a rewritten query,
|
||||
* because a sublink in jointree is not supported by this function.
|
||||
*/
|
||||
if (!skipData && !oldPopulated)
|
||||
CreateIvmTriggersOnBaseTables(dataQuery, matviewOid);
|
||||
|
||||
table_close(matviewRel, NoLock);
|
||||
|
||||
/* Roll back any GUC changes */
|
||||
|
|
@ -707,6 +759,8 @@ IVM_immediate_before(PG_FUNCTION_ARGS)
|
|||
/* If the view has more than one tables, we have to use an exclusive lock. */
|
||||
if (ex_lock)
|
||||
{
|
||||
FullTransactionId xid;
|
||||
|
||||
/*
|
||||
* Wait for concurrent transactions which update this materialized view at
|
||||
* READ COMMITED. This is needed to see changes committed in other
|
||||
|
|
@ -731,6 +785,21 @@ IVM_immediate_before(PG_FUNCTION_ARGS)
|
|||
errmsg("could not obtain lock on materialized view \"%s\" during incremental maintenance",
|
||||
relname)));
|
||||
}
|
||||
|
||||
/*
|
||||
* Even if we can acquire an lock, a concurrent transaction could have
|
||||
* updated the view incrementally and been committed before we acquired
|
||||
* the lock. Therefore, we have to check the transaction ID of the most
|
||||
* recent update of the view, and if this was in progress at the
|
||||
* transaction start, raise an error to prevent anomalies.
|
||||
*/
|
||||
xid = getLastUpdateXid(matviewOid);
|
||||
if (XidInMVCCSnapshot(XidFromFullTransactionId(xid), GetTransactionSnapshot()))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
|
||||
errmsg("the materialized view is incrementally updated in concurrent transaction"),
|
||||
errhint("The transaction might succeed if retried.")));
|
||||
|
||||
}
|
||||
else
|
||||
LockRelationOid(matviewOid, RowExclusiveLock);
|
||||
|
|
@ -746,13 +815,22 @@ IVM_immediate_before(PG_FUNCTION_ARGS)
|
|||
HASH_ENTER, &found);
|
||||
|
||||
/* On the first BEFORE to update the view, initialize trigger data */
|
||||
if (!found)
|
||||
if (!found || entry->snapshot == InvalidSnapshot)
|
||||
{
|
||||
Snapshot snapshot;
|
||||
|
||||
/*
|
||||
* Get a snapshot just before the table was modified for checking
|
||||
* tuple visibility in the pre-update state of the table.
|
||||
*
|
||||
* In READ COMMITTED, use the latest snapshot again to see the
|
||||
* results of concurrent transactions committed after the current
|
||||
* transaction started.
|
||||
*/
|
||||
Snapshot snapshot = GetActiveSnapshot();
|
||||
if (IsolationUsesXactSnapshot())
|
||||
snapshot = GetActiveSnapshot();
|
||||
else
|
||||
snapshot = GetTransactionSnapshot();
|
||||
|
||||
entry->matview_id = matviewOid;
|
||||
entry->before_trig_count = 0;
|
||||
|
|
@ -761,11 +839,17 @@ IVM_immediate_before(PG_FUNCTION_ARGS)
|
|||
entry->tables = NIL;
|
||||
entry->has_old = false;
|
||||
entry->has_new = false;
|
||||
|
||||
/*
|
||||
* If this is the first table modifying query in the transaction,
|
||||
* initialize the list of subxids.
|
||||
*/
|
||||
if (!found)
|
||||
entry->subxids = NIL;
|
||||
}
|
||||
|
||||
entry->before_trig_count++;
|
||||
|
||||
|
||||
return PointerGetDatum(NULL);
|
||||
}
|
||||
|
||||
|
|
@ -788,6 +872,7 @@ IVM_immediate_maintenance(PG_FUNCTION_ARGS)
|
|||
char *matviewOid_text = trigdata->tg_trigger->tgargs[0];
|
||||
Relation matviewRel;
|
||||
int old_depth = immv_maintenance_depth;
|
||||
SubTransactionId subxid;
|
||||
|
||||
Oid relowner;
|
||||
Tuplestorestate *old_tuplestore = NULL;
|
||||
|
|
@ -885,8 +970,17 @@ IVM_immediate_maintenance(PG_FUNCTION_ARGS)
|
|||
* If this is the last AFTER trigger call, continue and update the view.
|
||||
*/
|
||||
|
||||
/* record the subxid that updated the view incrementally */
|
||||
subxid = GetCurrentSubTransactionId();
|
||||
if (!list_member_xid(entry->subxids, subxid))
|
||||
{
|
||||
oldcxt = MemoryContextSwitchTo(TopTransactionContext);
|
||||
entry->subxids = lappend_xid(entry->subxids, subxid);
|
||||
MemoryContextSwitchTo(oldcxt);
|
||||
}
|
||||
|
||||
/*
|
||||
* Advance command counter to make the updated base table row locally
|
||||
* Advance command counter to make the updated base table rows locally
|
||||
* visible.
|
||||
*/
|
||||
CommandCounterIncrement();
|
||||
|
|
@ -897,10 +991,12 @@ IVM_immediate_maintenance(PG_FUNCTION_ARGS)
|
|||
Assert(matviewRel->rd_rel->relkind == RELKIND_RELATION);
|
||||
|
||||
/*
|
||||
* Get and push the latast snapshot to see any changes which is committed
|
||||
* during waiting in other transactions at READ COMMITTED level.
|
||||
* In READ COMMITTED, get and push the latest snapshot again to see the
|
||||
* results of concurrent transactions committed after the current
|
||||
* transaction started.
|
||||
*/
|
||||
PushActiveSnapshot(GetTransactionSnapshot());
|
||||
if (!IsolationUsesXactSnapshot())
|
||||
PushActiveSnapshot(GetTransactionSnapshot());
|
||||
|
||||
/*
|
||||
* Check for active uses of the relation in the current transaction, such
|
||||
|
|
@ -985,10 +1081,11 @@ IVM_immediate_maintenance(PG_FUNCTION_ARGS)
|
|||
}
|
||||
|
||||
/* Clean up hash entry and delete tuplestores */
|
||||
clean_up_IVM_hash_entry(entry, false);
|
||||
clean_up_IVM_hash_entry(entry, false, InvalidSubTransactionId);
|
||||
|
||||
/* Pop the original snapshot. */
|
||||
PopActiveSnapshot();
|
||||
if (!IsolationUsesXactSnapshot())
|
||||
PopActiveSnapshot();
|
||||
|
||||
table_close(matviewRel, NoLock);
|
||||
|
||||
|
|
@ -1148,7 +1245,7 @@ IVM_immediate_maintenance(PG_FUNCTION_ARGS)
|
|||
}
|
||||
|
||||
/* Clean up hash entry and delete tuplestores */
|
||||
clean_up_IVM_hash_entry(entry, false);
|
||||
clean_up_IVM_hash_entry(entry, false, InvalidSubTransactionId);
|
||||
if (old_tuplestore)
|
||||
{
|
||||
dest_old->rDestroy(dest_old);
|
||||
|
|
@ -1161,7 +1258,8 @@ IVM_immediate_maintenance(PG_FUNCTION_ARGS)
|
|||
}
|
||||
|
||||
/* Pop the original snapshot. */
|
||||
PopActiveSnapshot();
|
||||
if (!IsolationUsesXactSnapshot())
|
||||
PopActiveSnapshot();
|
||||
|
||||
table_close(matviewRel, NoLock);
|
||||
|
||||
|
|
@ -1839,7 +1937,7 @@ calc_delta(MV_TriggerTable *table, List *rte_path, Query *query,
|
|||
in_delta_calculation = true;
|
||||
|
||||
/* Generate old delta */
|
||||
if (list_length(table->old_rtes) > 0)
|
||||
if (dest_old && list_length(table->old_rtes) > 0)
|
||||
{
|
||||
/* Replace the modified table with the old delta table and calculate the old view delta. */
|
||||
lfirst(lc) = union_ENRs(rte, table, table->old_rtes, "old", queryEnv);
|
||||
|
|
@ -1847,7 +1945,7 @@ calc_delta(MV_TriggerTable *table, List *rte_path, Query *query,
|
|||
}
|
||||
|
||||
/* Generate new delta */
|
||||
if (list_length(table->new_rtes) > 0)
|
||||
if (dest_new && list_length(table->new_rtes) > 0)
|
||||
{
|
||||
/* Replace the modified table with the new delta table and calculate the new view delta*/
|
||||
lfirst(lc) = union_ENRs(rte, table, table->new_rtes, "new", queryEnv);
|
||||
|
|
@ -2652,6 +2750,7 @@ apply_new_delta_with_count(const char *matviewname, const char* deltaname_new,
|
|||
matviewname, target_list->data,
|
||||
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);
|
||||
}
|
||||
|
|
@ -3218,10 +3317,11 @@ mv_BuildQueryKey(MV_QueryKey *key, Oid matview_id, int32 query_type)
|
|||
* AtAbort_IVM
|
||||
*
|
||||
* Clean up hash entries for all materialized views. This is called at
|
||||
* transaction abort.
|
||||
* (sub-)transaction abort. When the top-level transaction is aborted,
|
||||
* InvalidSubTransactionId is set to subxid.
|
||||
*/
|
||||
void
|
||||
AtAbort_IVM()
|
||||
AtAbort_IVM(SubTransactionId subxid)
|
||||
{
|
||||
HASH_SEQ_STATUS seq;
|
||||
MV_TriggerHashEntry *entry;
|
||||
|
|
@ -3230,7 +3330,38 @@ AtAbort_IVM()
|
|||
{
|
||||
hash_seq_init(&seq, mv_trigger_info);
|
||||
while ((entry = hash_seq_search(&seq)) != NULL)
|
||||
clean_up_IVM_hash_entry(entry, true);
|
||||
clean_up_IVM_hash_entry(entry, true, subxid);
|
||||
}
|
||||
|
||||
in_delta_calculation = false;
|
||||
}
|
||||
|
||||
/*
|
||||
* AtPreCommit_IVM
|
||||
*
|
||||
* Store the transaction ID that updated the view incrementally
|
||||
* into the pg_ivm_immv catalog at transaction commit.
|
||||
*/
|
||||
void
|
||||
AtPreCommit_IVM()
|
||||
{
|
||||
HASH_SEQ_STATUS seq;
|
||||
MV_TriggerHashEntry *entry;
|
||||
|
||||
if (mv_trigger_info)
|
||||
{
|
||||
/*
|
||||
* For each view that was incrementally updated in the transaction,
|
||||
* record the transaction ID into the pg_ivm_immv catalog, and perform
|
||||
* the final clean up of the entry.
|
||||
*/
|
||||
hash_seq_init(&seq, mv_trigger_info);
|
||||
while ((entry = hash_seq_search(&seq)) != NULL)
|
||||
{
|
||||
bool found;
|
||||
setLastUpdateXid(entry->matview_id, GetTopFullTransactionId());
|
||||
hash_search(mv_trigger_info, (void *) &entry->matview_id, HASH_REMOVE, &found);
|
||||
}
|
||||
}
|
||||
|
||||
in_delta_calculation = false;
|
||||
|
|
@ -3240,14 +3371,18 @@ AtAbort_IVM()
|
|||
* clean_up_IVM_hash_entry
|
||||
*
|
||||
* Clean up tuple stores and hash entries for a materialized view after its
|
||||
* maintenance finished.
|
||||
* maintenance finished. This is called at the end of table modifying query
|
||||
* or (sub-)transaction abort. When the top-level transaction is aborted,
|
||||
* InvalidSubTransactionId is set to subxid.
|
||||
*/
|
||||
static void
|
||||
clean_up_IVM_hash_entry(MV_TriggerHashEntry *entry, bool is_abort)
|
||||
clean_up_IVM_hash_entry(MV_TriggerHashEntry *entry, bool is_abort,
|
||||
SubTransactionId subxid)
|
||||
{
|
||||
bool found;
|
||||
ListCell *lc;
|
||||
|
||||
/* clean up tuple stores */
|
||||
foreach(lc, entry->tables)
|
||||
{
|
||||
MV_TriggerTable *table = (MV_TriggerTable *) lfirst(lc);
|
||||
|
|
@ -3273,12 +3408,136 @@ clean_up_IVM_hash_entry(MV_TriggerHashEntry *entry, bool is_abort)
|
|||
}
|
||||
}
|
||||
list_free(entry->tables);
|
||||
entry->tables = NIL;
|
||||
|
||||
if (!is_abort)
|
||||
if (is_abort)
|
||||
{
|
||||
bool remove_entry = false;
|
||||
|
||||
/*
|
||||
* When the top-level transaction is aborted, remove all subxids.
|
||||
* When a sub-transaction is aborted, remove only its subxid.
|
||||
*/
|
||||
if (subxid == InvalidSubTransactionId)
|
||||
remove_entry = true;
|
||||
else
|
||||
{
|
||||
foreach(lc, entry->subxids)
|
||||
{
|
||||
if (lfirst_xid(lc) == subxid)
|
||||
{
|
||||
entry->subxids = list_delete_cell(entry->subxids, lc);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If all the subxid are removed, it means that the view was not
|
||||
* updated at all in this transaction.
|
||||
*/
|
||||
if (list_length(entry->subxids) == 0)
|
||||
remove_entry = true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Remove entries of not updated views from the hash table.
|
||||
*/
|
||||
if (remove_entry)
|
||||
hash_search(mv_trigger_info, (void *) &entry->matview_id, HASH_REMOVE, &found);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* When the query sucsessully finished, unregister the snapshot */
|
||||
UnregisterSnapshot(entry->snapshot);
|
||||
}
|
||||
|
||||
entry->snapshot = InvalidSnapshot;
|
||||
}
|
||||
|
||||
hash_search(mv_trigger_info, (void *) &entry->matview_id, HASH_REMOVE, &found);
|
||||
/*
|
||||
* setLastUpdateXid
|
||||
*
|
||||
* Store the transaction ID that updated the view incremenally into the
|
||||
* pg_ivm_immv catalog.
|
||||
*/
|
||||
static void
|
||||
setLastUpdateXid(Oid immv_oid, FullTransactionId xid)
|
||||
{
|
||||
Relation pgIvmImmv = table_open(PgIvmImmvRelationId(), ShareRowExclusiveLock);
|
||||
TupleDesc tupdesc = RelationGetDescr(pgIvmImmv);
|
||||
SysScanDesc scan;
|
||||
ScanKeyData key;
|
||||
HeapTuple tup;
|
||||
Datum values[Natts_pg_ivm_immv];
|
||||
bool nulls[Natts_pg_ivm_immv];
|
||||
bool replaces[Natts_pg_ivm_immv];
|
||||
HeapTuple newtup = NULL;
|
||||
|
||||
ScanKeyInit(&key,
|
||||
Anum_pg_ivm_immv_immvrelid,
|
||||
BTEqualStrategyNumber, F_OIDEQ,
|
||||
ObjectIdGetDatum(immv_oid));
|
||||
scan = systable_beginscan(pgIvmImmv, PgIvmImmvPrimaryKeyIndexId(),
|
||||
true, NULL, 1, &key);
|
||||
tup = systable_getnext(scan);
|
||||
|
||||
memset(values, 0, sizeof(values));
|
||||
values[Anum_pg_ivm_immv_lastivmupdate -1 ] = FullTransactionIdGetDatum(xid);
|
||||
MemSet(nulls, false, sizeof(nulls));
|
||||
MemSet(replaces, false, sizeof(replaces));
|
||||
replaces[Anum_pg_ivm_immv_lastivmupdate -1 ] = true;
|
||||
|
||||
newtup = heap_modify_tuple(tup, tupdesc, values, nulls, replaces);
|
||||
|
||||
CatalogTupleUpdate(pgIvmImmv, &newtup->t_self, newtup);
|
||||
heap_freetuple(newtup);
|
||||
|
||||
/*
|
||||
* Advance command counter to make the updated pg_ivm_immv row locally
|
||||
* visible.
|
||||
*/
|
||||
CommandCounterIncrement();
|
||||
|
||||
systable_endscan(scan);
|
||||
table_close(pgIvmImmv, ShareRowExclusiveLock);
|
||||
}
|
||||
|
||||
/*
|
||||
* getLastUpdateXid
|
||||
*
|
||||
* Get the most recent transaction ID that updated the view incrementally
|
||||
* from the pg_ivm_immv catalog.
|
||||
*/
|
||||
static FullTransactionId
|
||||
getLastUpdateXid(Oid immv_oid)
|
||||
{
|
||||
Relation pgIvmImmv = table_open(PgIvmImmvRelationId(), AccessShareLock);
|
||||
TupleDesc tupdesc = RelationGetDescr(pgIvmImmv);
|
||||
SysScanDesc scan;
|
||||
ScanKeyData key;
|
||||
HeapTuple tup;
|
||||
bool isnull;
|
||||
Datum datum;
|
||||
FullTransactionId xid = InvalidFullTransactionId;
|
||||
|
||||
ScanKeyInit(&key,
|
||||
Anum_pg_ivm_immv_immvrelid,
|
||||
BTEqualStrategyNumber, F_OIDEQ,
|
||||
ObjectIdGetDatum(immv_oid));
|
||||
scan = systable_beginscan(pgIvmImmv, PgIvmImmvPrimaryKeyIndexId(),
|
||||
true, NULL, 1, &key);
|
||||
|
||||
tup = systable_getnext(scan);
|
||||
datum = heap_getattr(tup, Anum_pg_ivm_immv_lastivmupdate, tupdesc, &isnull);
|
||||
|
||||
if (!isnull)
|
||||
xid = DatumGetFullTransactionId(datum);
|
||||
|
||||
systable_endscan(scan);
|
||||
table_close(pgIvmImmv, NoLock);
|
||||
|
||||
return xid;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ CREATE TABLE pgivm.pg_ivm_immv(
|
|||
immvrelid regclass NOT NULL,
|
||||
viewdef text NOT NULL,
|
||||
ispopulated bool NOT NULL,
|
||||
lastivmupdate xid8,
|
||||
|
||||
CONSTRAINT pg_ivm_immv_pkey PRIMARY KEY (immvrelid)
|
||||
);
|
||||
|
|
|
|||
|
|
@ -12,5 +12,7 @@ ALTER FUNCTION "IVM_prevent_immv_change"() SET SCHEMA pgivm;
|
|||
|
||||
GRANT USAGE ON SCHEMA pgivm TO PUBLIC;
|
||||
|
||||
ALTER TABLE pgivm.pg_ivm_immv ADD COLUMN lastivmupdate xid8;
|
||||
|
||||
-- drop a garbage
|
||||
DROP SCHEMA __pg_ivm__;
|
||||
|
|
|
|||
8
pg_ivm.c
8
pg_ivm.c
|
|
@ -63,8 +63,10 @@ PG_FUNCTION_INFO_V1(get_immv_def);
|
|||
static void
|
||||
IvmXactCallback(XactEvent event, void *arg)
|
||||
{
|
||||
if (event == XACT_EVENT_ABORT)
|
||||
AtAbort_IVM();
|
||||
if (event == XACT_EVENT_PRE_COMMIT)
|
||||
AtPreCommit_IVM();
|
||||
else if (event == XACT_EVENT_ABORT)
|
||||
AtAbort_IVM(InvalidSubTransactionId);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -72,7 +74,7 @@ IvmSubXactCallback(SubXactEvent event, SubTransactionId mySubid,
|
|||
SubTransactionId parentSubid, void *arg)
|
||||
{
|
||||
if (event == SUBXACT_EVENT_ABORT_SUB)
|
||||
AtAbort_IVM();
|
||||
AtAbort_IVM(mySubid);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
8
pg_ivm.h
8
pg_ivm.h
|
|
@ -20,11 +20,12 @@
|
|||
#include "tcop/dest.h"
|
||||
#include "utils/queryenvironment.h"
|
||||
|
||||
#define Natts_pg_ivm_immv 3
|
||||
#define Natts_pg_ivm_immv 4
|
||||
|
||||
#define Anum_pg_ivm_immv_immvrelid 1
|
||||
#define Anum_pg_ivm_immv_viewdef 2
|
||||
#define Anum_pg_ivm_immv_ispopulated 3
|
||||
#define Anum_pg_ivm_immv_lastivmupdate 4
|
||||
|
||||
/* pg_ivm.c */
|
||||
|
||||
|
|
@ -48,14 +49,15 @@ extern void makeIvmAggColumn(ParseState *pstate, Aggref *aggref, char *resname,
|
|||
extern Query *get_immv_query(Relation matviewRel);
|
||||
extern ObjectAddress ExecRefreshImmv(const RangeVar *relation, bool skipData,
|
||||
const char *queryString, QueryCompletion *qc);
|
||||
extern ObjectAddress RefreshImmvByOid(Oid matviewOid, bool skipData,
|
||||
extern ObjectAddress RefreshImmvByOid(Oid matviewOid, bool is_create, bool skipData,
|
||||
const char *queryString, QueryCompletion *qc);
|
||||
extern bool ImmvIncrementalMaintenanceIsEnabled(void);
|
||||
extern Datum IVM_immediate_before(PG_FUNCTION_ARGS);
|
||||
extern Datum IVM_immediate_maintenance(PG_FUNCTION_ARGS);
|
||||
extern Query* rewrite_query_for_exists_subquery(Query *query);
|
||||
extern Datum ivm_visible_in_prestate(PG_FUNCTION_ARGS);
|
||||
extern void AtAbort_IVM(void);
|
||||
extern void AtAbort_IVM(SubTransactionId subtxid);
|
||||
extern void AtPreCommit_IVM(void);
|
||||
extern char *getColumnNameStartWith(RangeTblEntry *rte, char *str, int *attnum);
|
||||
extern bool isIvmName(const char *s);
|
||||
|
||||
|
|
|
|||
47
specs/create_insert.spec
Normal file
47
specs/create_insert.spec
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
# Test interaction between concurrent transactions performing
|
||||
# create_immv and insert in READ COMMITTED isolation level
|
||||
|
||||
setup
|
||||
{
|
||||
CREATE TABLE a (i int);
|
||||
INSERT INTO a VALUES (1);
|
||||
CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i;
|
||||
}
|
||||
|
||||
teardown
|
||||
{
|
||||
DROP FUNCTION check_mv();
|
||||
DROP TABLE mv;
|
||||
DROP VIEW v;
|
||||
DROP TABLE a;
|
||||
}
|
||||
|
||||
session tx1
|
||||
setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; }
|
||||
step s1 { SELECT; }
|
||||
step create {
|
||||
SELECT pgivm.create_immv('mv(x,y)', 'SELECT * FROM a a1, a a2 WHERE a1.i = a2.i');
|
||||
CREATE FUNCTION check_mv() RETURNS text AS
|
||||
$$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END
|
||||
FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL
|
||||
(SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) $$ LANGUAGE sql;
|
||||
}
|
||||
step check1 {SELECT check_mv();}
|
||||
step c1 { COMMIT; }
|
||||
step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); }
|
||||
|
||||
session tx2
|
||||
setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; }
|
||||
step s2 { SELECT; }
|
||||
step insert { INSERT INTO a VALUES (2); }
|
||||
step check2 {SELECT check_mv(); }
|
||||
step c2 { COMMIT; }
|
||||
|
||||
permutation s1 create s2 insert c1 check2 c2 mv
|
||||
permutation s1 create s2 c1 insert check2 c2 mv
|
||||
permutation s1 s2 create insert c1 check2 c2 mv
|
||||
permutation s1 s2 insert create c2 check1 c1 mv
|
||||
permutation s1 s2 create c1 insert check2 c2 mv
|
||||
permutation s2 insert s1 create c2 check1 c1 mv
|
||||
permutation s2 insert s1 c2 create check1 c1 mv
|
||||
permutation s2 s1 insert c2 create check1 c1 mv
|
||||
54
specs/create_insert2.spec
Normal file
54
specs/create_insert2.spec
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
# Test interaction between concurrent transactions performing
|
||||
# create_immv and insert in REPEATABLE READ isolation level
|
||||
#
|
||||
# Note:
|
||||
# In this isolation level, it is possible that create_immv could
|
||||
# create an inconsistent view not including effects of a concurrent
|
||||
# transaction. So, an warning message is raised to suggest using it
|
||||
# in READ COMMITTED or executing refresh_immv to make sure to
|
||||
# make the view contents consistent.
|
||||
|
||||
setup
|
||||
{
|
||||
CREATE TABLE a (i int);
|
||||
INSERT INTO a VALUES (1);
|
||||
CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i;
|
||||
}
|
||||
|
||||
teardown
|
||||
{
|
||||
DROP FUNCTION check_mv();
|
||||
DROP TABLE mv;
|
||||
DROP VIEW v;
|
||||
DROP TABLE a;
|
||||
}
|
||||
|
||||
session tx1
|
||||
setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; }
|
||||
step s1 { SELECT; }
|
||||
step create {
|
||||
SELECT pgivm.create_immv('mv(x,y)', 'SELECT * FROM a a1, a a2 WHERE a1.i = a2.i');
|
||||
CREATE FUNCTION check_mv() RETURNS text AS
|
||||
$$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END
|
||||
FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL
|
||||
(SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) $$ LANGUAGE sql;
|
||||
}
|
||||
step check1 {SELECT check_mv();}
|
||||
step c1 { COMMIT; }
|
||||
step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); }
|
||||
|
||||
session tx2
|
||||
setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; }
|
||||
step s2 { SELECT; }
|
||||
step insert { INSERT INTO a VALUES (2); }
|
||||
step check2 {SELECT check_mv(); }
|
||||
step c2 { COMMIT; }
|
||||
|
||||
permutation s1 create s2 insert c1 check2 c2 mv
|
||||
permutation s1 create s2 c1 insert check2 c2 mv
|
||||
permutation s1 s2 create insert c1 check2 c2 mv
|
||||
permutation s1 s2 insert create c2 check1 c1 mv
|
||||
permutation s1 s2 create c1 insert check2 c2 mv
|
||||
permutation s2 insert s1 create c2 check1 c1 mv
|
||||
permutation s2 insert s1 c2 create check1 c1 mv
|
||||
permutation s2 s1 insert c2 create check1 c1 mv
|
||||
54
specs/create_insert3.spec
Normal file
54
specs/create_insert3.spec
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
# Test interaction between concurrent transactions performing
|
||||
# create_immv and insert in SERIALIZABLE isolation level
|
||||
#
|
||||
# Note:
|
||||
# In this isolation level, it is possible that create_immv could
|
||||
# create an inconsistent view not including effects of a concurrent
|
||||
# transaction. So, an warning message is raised to suggest using it
|
||||
# in READ COMMITTED or executing refresh_immv to make sure to
|
||||
# make the view contents consistent.
|
||||
|
||||
setup
|
||||
{
|
||||
CREATE TABLE a (i int);
|
||||
INSERT INTO a VALUES (1);
|
||||
CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i;
|
||||
}
|
||||
|
||||
teardown
|
||||
{
|
||||
DROP FUNCTION check_mv();
|
||||
DROP TABLE mv;
|
||||
DROP VIEW v;
|
||||
DROP TABLE a;
|
||||
}
|
||||
|
||||
session tx1
|
||||
setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; }
|
||||
step s1 { SELECT; }
|
||||
step create {
|
||||
SELECT pgivm.create_immv('mv(x,y)', 'SELECT * FROM a a1, a a2 WHERE a1.i = a2.i');
|
||||
CREATE FUNCTION check_mv() RETURNS text AS
|
||||
$$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END
|
||||
FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL
|
||||
(SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) $$ LANGUAGE sql;
|
||||
}
|
||||
step check1 {SELECT check_mv();}
|
||||
step c1 { COMMIT; }
|
||||
step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); }
|
||||
|
||||
session tx2
|
||||
setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; }
|
||||
step s2 { SELECT; }
|
||||
step insert { INSERT INTO a VALUES (2); }
|
||||
step check2 {SELECT check_mv(); }
|
||||
step c2 { COMMIT; }
|
||||
|
||||
permutation s1 create s2 insert c1 check2 c2 mv
|
||||
permutation s1 create s2 c1 insert check2 c2 mv
|
||||
permutation s1 s2 create insert c1 check2 c2 mv
|
||||
permutation s1 s2 insert create c2 check1 c1 mv
|
||||
permutation s1 s2 create c1 insert check2 c2 mv
|
||||
permutation s2 insert s1 create c2 check1 c1 mv
|
||||
permutation s2 insert s1 c2 create check1 c1 mv
|
||||
permutation s2 s1 insert c2 create check1 c1 mv
|
||||
62
specs/insert_insert.spec
Normal file
62
specs/insert_insert.spec
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
# Test interaction between concurrent transactions performing
|
||||
# table modifications in READ COMMITTED isolation level
|
||||
|
||||
setup
|
||||
{
|
||||
CREATE TABLE a (i int, j int);
|
||||
CREATE TABLE b (i int, j int);
|
||||
INSERT INTO a VALUES (1,10);
|
||||
INSERT INTO b VALUES (1,100);
|
||||
SELECT pgivm.create_immv('mv(x,y,z)',
|
||||
'SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i');
|
||||
CREATE VIEW v(x,y,z) AS
|
||||
SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i;
|
||||
CREATE FUNCTION check_mv() RETURNS text AS
|
||||
$$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END
|
||||
FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL
|
||||
(SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) $$ LANGUAGE sql;
|
||||
}
|
||||
|
||||
teardown
|
||||
{
|
||||
DROP FUNCTION check_mv();
|
||||
DROP TABLE mv;
|
||||
DROP VIEW v;
|
||||
DROP TABLE a;
|
||||
DROP TABLE b;
|
||||
}
|
||||
|
||||
session tx1
|
||||
setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; }
|
||||
step s1 { SELECT; }
|
||||
step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); }
|
||||
step update1 { UPDATE a SET j = 11 WHERE i = 1; }
|
||||
step check1 { SELECT check_mv();}
|
||||
step c1 { COMMIT; }
|
||||
step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); }
|
||||
|
||||
session tx2
|
||||
setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; }
|
||||
step s2 { SELECT; }
|
||||
step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); }
|
||||
step update2 { UPDATE b SET j = 111 WHERE i = 1; }
|
||||
step check2 { SELECT check_mv(); }
|
||||
step c2 { COMMIT; }
|
||||
|
||||
permutation s1 update1 s2 update2 c1 check2 c2 mv
|
||||
permutation s1 update1 s2 c1 update2 check2 c2 mv
|
||||
permutation s1 s2 update1 update2 c1 check2 c2 mv
|
||||
permutation s1 s2 update2 update1 c2 check1 c1 mv
|
||||
permutation s1 s2 update1 c1 update2 check2 c2 mv
|
||||
permutation s2 update2 s1 update1 c2 check1 c1 mv
|
||||
permutation s2 update2 s1 c2 update1 check1 c1 mv
|
||||
permutation s2 s1 update2 c2 update1 check1 c1 mv
|
||||
|
||||
permutation s1 insert1 s2 insert2 c1 check2 c2 mv
|
||||
permutation s1 insert1 s2 c1 insert2 check2 c2 mv
|
||||
permutation s1 s2 insert1 insert2 c1 check2 c2 mv
|
||||
permutation s1 s2 insert2 insert1 c2 check1 c1 mv
|
||||
permutation s1 s2 insert1 c1 insert2 check2 c2 mv
|
||||
permutation s2 insert2 s1 insert1 c2 check1 c1 mv
|
||||
permutation s2 insert2 s1 c2 insert1 check1 c1 mv
|
||||
permutation s2 s1 insert2 c2 insert1 check1 c1 mv
|
||||
62
specs/insert_insert2.spec
Normal file
62
specs/insert_insert2.spec
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
# Test interaction between concurrent transactions performing
|
||||
# table modifications in REPEATABLE READ isolation level
|
||||
|
||||
setup
|
||||
{
|
||||
CREATE TABLE a (i int, j int);
|
||||
CREATE TABLE b (i int, j int);
|
||||
INSERT INTO a VALUES (1,10);
|
||||
INSERT INTO b VALUES (1,100);
|
||||
SELECT pgivm.create_immv('mv(x,y,z)',
|
||||
'SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i');
|
||||
CREATE VIEW v(x,y,z) AS
|
||||
SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i;
|
||||
CREATE FUNCTION check_mv() RETURNS text AS
|
||||
$$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END
|
||||
FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL
|
||||
(SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) $$ LANGUAGE sql;
|
||||
}
|
||||
|
||||
teardown
|
||||
{
|
||||
DROP FUNCTION check_mv();
|
||||
DROP TABLE mv;
|
||||
DROP VIEW v;
|
||||
DROP TABLE a;
|
||||
DROP TABLE b;
|
||||
}
|
||||
|
||||
session tx1
|
||||
setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; }
|
||||
step s1 { SELECT; }
|
||||
step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); }
|
||||
step update1 { UPDATE a SET j = 11 WHERE i = 1; }
|
||||
step check1 { SELECT check_mv();}
|
||||
step c1 { COMMIT; }
|
||||
step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); }
|
||||
|
||||
session tx2
|
||||
setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; }
|
||||
step s2 { SELECT; }
|
||||
step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); }
|
||||
step update2 { UPDATE b SET j = 111 WHERE i = 1; }
|
||||
step check2 { SELECT check_mv(); }
|
||||
step c2 { COMMIT; }
|
||||
|
||||
permutation s1 update1 s2 update2 c1 check2 c2 mv
|
||||
permutation s1 update1 s2 c1 update2 check2 c2 mv
|
||||
permutation s1 s2 update1 update2 c1 check2 c2 mv
|
||||
permutation s1 s2 update2 update1 c2 check1 c1 mv
|
||||
permutation s1 s2 update1 c1 update2 check2 c2 mv
|
||||
permutation s2 update2 s1 update1 c2 check1 c1 mv
|
||||
permutation s2 update2 s1 c2 update1 check1 c1 mv
|
||||
permutation s2 s1 update2 c2 update1 check1 c1 mv
|
||||
|
||||
permutation s1 insert1 s2 insert2 c1 check2 c2 mv
|
||||
permutation s1 insert1 s2 c1 insert2 check2 c2 mv
|
||||
permutation s1 s2 insert1 insert2 c1 check2 c2 mv
|
||||
permutation s1 s2 insert2 insert1 c2 check1 c1 mv
|
||||
permutation s1 s2 insert1 c1 insert2 check2 c2 mv
|
||||
permutation s2 insert2 s1 insert1 c2 check1 c1 mv
|
||||
permutation s2 insert2 s1 c2 insert1 check1 c1 mv
|
||||
permutation s2 s1 insert2 c2 insert1 check1 c1 mv
|
||||
62
specs/insert_insert3.spec
Normal file
62
specs/insert_insert3.spec
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
# Test interaction between concurrent transactions performing
|
||||
# table modifications in SERIALIZABLE isolation level
|
||||
|
||||
setup
|
||||
{
|
||||
CREATE TABLE a (i int, j int);
|
||||
CREATE TABLE b (i int, j int);
|
||||
INSERT INTO a VALUES (1,10);
|
||||
INSERT INTO b VALUES (1,100);
|
||||
SELECT pgivm.create_immv('mv(x,y,z)',
|
||||
'SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i');
|
||||
CREATE VIEW v(x,y,z) AS
|
||||
SELECT a1.j, a2.j,b.j FROM a AS a1, a AS a2,b WHERE a1.i = a2.i AND a1.i = b.i;
|
||||
CREATE FUNCTION check_mv() RETURNS text AS
|
||||
$$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END
|
||||
FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL
|
||||
(SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) $$ LANGUAGE sql;
|
||||
}
|
||||
|
||||
teardown
|
||||
{
|
||||
DROP FUNCTION check_mv();
|
||||
DROP TABLE mv;
|
||||
DROP VIEW v;
|
||||
DROP TABLE a;
|
||||
DROP TABLE b;
|
||||
}
|
||||
|
||||
session tx1
|
||||
setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; }
|
||||
step s1 { SELECT; }
|
||||
step insert1 { INSERT INTO a VALUES (2,20); INSERT INTO b VALUES (2,200); }
|
||||
step update1 { UPDATE a SET j = 11 WHERE i = 1; }
|
||||
step check1 { SELECT check_mv();}
|
||||
step c1 { COMMIT; }
|
||||
step mv { SELECT * FROM mv ORDER BY 1,2,3; SELECT check_mv(); }
|
||||
|
||||
session tx2
|
||||
setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; }
|
||||
step s2 { SELECT; }
|
||||
step insert2 { INSERT INTO a VALUES (1,11), (2,21); INSERT INTO b VALUES (2,201); }
|
||||
step update2 { UPDATE b SET j = 111 WHERE i = 1; }
|
||||
step check2 { SELECT check_mv(); }
|
||||
step c2 { COMMIT; }
|
||||
|
||||
permutation s1 update1 s2 update2 c1 check2 c2 mv
|
||||
permutation s1 update1 s2 c1 update2 check2 c2 mv
|
||||
permutation s1 s2 update1 update2 c1 check2 c2 mv
|
||||
permutation s1 s2 update2 update1 c2 check1 c1 mv
|
||||
permutation s1 s2 update1 c1 update2 check2 c2 mv
|
||||
permutation s2 update2 s1 update1 c2 check1 c1 mv
|
||||
permutation s2 update2 s1 c2 update1 check1 c1 mv
|
||||
permutation s2 s1 update2 c2 update1 check1 c1 mv
|
||||
|
||||
permutation s1 insert1 s2 insert2 c1 check2 c2 mv
|
||||
permutation s1 insert1 s2 c1 insert2 check2 c2 mv
|
||||
permutation s1 s2 insert1 insert2 c1 check2 c2 mv
|
||||
permutation s1 s2 insert2 insert1 c2 check1 c1 mv
|
||||
permutation s1 s2 insert1 c1 insert2 check2 c2 mv
|
||||
permutation s2 insert2 s1 insert1 c2 check1 c1 mv
|
||||
permutation s2 insert2 s1 c2 insert1 check1 c1 mv
|
||||
permutation s2 s1 insert2 c2 insert1 check1 c1 mv
|
||||
46
specs/refresh_insert.spec
Normal file
46
specs/refresh_insert.spec
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
# Test interaction between concurrent transactions performing
|
||||
# refresh_immv and insert in READ COMMITTED isolation level
|
||||
|
||||
setup
|
||||
{
|
||||
CREATE TABLE a (i int);
|
||||
INSERT INTO a VALUES (1);
|
||||
SELECT pgivm.create_immv('mv(x,y)', 'SELECT * FROM a a1, a a2 WHERE a1.i = a2.i');
|
||||
CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i;
|
||||
CREATE FUNCTION check_mv() RETURNS text AS
|
||||
$$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END
|
||||
FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL
|
||||
(SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) $$ LANGUAGE sql;
|
||||
}
|
||||
|
||||
teardown
|
||||
{
|
||||
DROP FUNCTION check_mv();
|
||||
DROP TABLE mv;
|
||||
DROP VIEW v;
|
||||
DROP TABLE a;
|
||||
}
|
||||
|
||||
session tx1
|
||||
setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; }
|
||||
step s1 { SELECT; }
|
||||
step refresh { SELECT pgivm.refresh_immv('mv', true); }
|
||||
step check1 {SELECT check_mv();}
|
||||
step c1 { COMMIT; }
|
||||
step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); }
|
||||
|
||||
session tx2
|
||||
setup { BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; }
|
||||
step s2 { SELECT; }
|
||||
step insert { INSERT INTO a VALUES (2); }
|
||||
step check2 {SELECT check_mv(); }
|
||||
step c2 { COMMIT; }
|
||||
|
||||
permutation s1 refresh s2 insert c1 check2 c2 mv
|
||||
permutation s1 refresh s2 c1 insert check2 c2 mv
|
||||
permutation s1 s2 refresh insert c1 check2 c2 mv
|
||||
permutation s1 s2 insert refresh c2 check1 c1 mv
|
||||
permutation s1 s2 refresh c1 insert check2 c2 mv
|
||||
permutation s2 insert s1 refresh c2 check1 c1 mv
|
||||
permutation s2 insert s1 c2 refresh check1 c1 mv
|
||||
permutation s2 s1 insert c2 refresh check1 c1 mv
|
||||
46
specs/refresh_insert2.spec
Normal file
46
specs/refresh_insert2.spec
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
# Test interaction between concurrent transactions performing
|
||||
# refresh_immv and insert in REPEATABLE READ isolation level
|
||||
|
||||
setup
|
||||
{
|
||||
CREATE TABLE a (i int);
|
||||
INSERT INTO a VALUES (1);
|
||||
SELECT pgivm.create_immv('mv(x,y)', 'SELECT * FROM a a1, a a2 WHERE a1.i = a2.i');
|
||||
CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i;
|
||||
CREATE FUNCTION check_mv() RETURNS text AS
|
||||
$$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END
|
||||
FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL
|
||||
(SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) $$ LANGUAGE sql;
|
||||
}
|
||||
|
||||
teardown
|
||||
{
|
||||
DROP FUNCTION check_mv();
|
||||
DROP TABLE mv;
|
||||
DROP VIEW v;
|
||||
DROP TABLE a;
|
||||
}
|
||||
|
||||
session tx1
|
||||
setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; }
|
||||
step s1 { SELECT; }
|
||||
step refresh { SELECT pgivm.refresh_immv('mv', true); }
|
||||
step check1 {SELECT check_mv();}
|
||||
step c1 { COMMIT; }
|
||||
step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); }
|
||||
|
||||
session tx2
|
||||
setup { BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; }
|
||||
step s2 { SELECT; }
|
||||
step insert { INSERT INTO a VALUES (2); }
|
||||
step check2 {SELECT check_mv(); }
|
||||
step c2 { COMMIT; }
|
||||
|
||||
permutation s1 refresh s2 insert c1 check2 c2 mv
|
||||
permutation s1 refresh s2 c1 insert check2 c2 mv
|
||||
permutation s1 s2 refresh insert c1 check2 c2 mv
|
||||
permutation s1 s2 insert refresh c2 check1 c1 mv
|
||||
permutation s1 s2 refresh c1 insert check2 c2 mv
|
||||
permutation s2 insert s1 refresh c2 check1 c1 mv
|
||||
permutation s2 insert s1 c2 refresh check1 c1 mv
|
||||
permutation s2 s1 insert c2 refresh check1 c1 mv
|
||||
46
specs/refresh_insert3.spec
Normal file
46
specs/refresh_insert3.spec
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
# Test interaction between concurrent transactions performing
|
||||
# refresh_immv and insert in SERIALIZABLE isolation level
|
||||
|
||||
setup
|
||||
{
|
||||
CREATE TABLE a (i int);
|
||||
INSERT INTO a VALUES (1);
|
||||
SELECT pgivm.create_immv('mv(x,y)', 'SELECT * FROM a a1, a a2 WHERE a1.i = a2.i');
|
||||
CREATE VIEW v(x,y) AS SELECT * FROM a AS a1, a AS a2 WHERE a1.i = a2.i;
|
||||
CREATE FUNCTION check_mv() RETURNS text AS
|
||||
$$ SELECT CASE WHEN count(*) = 0 THEN 'ok' ELSE 'ng' END
|
||||
FROM ((SELECT * FROM mv EXCEPT ALL SELECT * FROM v) UNION ALL
|
||||
(SELECT * FROM v EXCEPT ALL SELECT * FROM mv)) $$ LANGUAGE sql;
|
||||
}
|
||||
|
||||
teardown
|
||||
{
|
||||
DROP FUNCTION check_mv();
|
||||
DROP TABLE mv;
|
||||
DROP VIEW v;
|
||||
DROP TABLE a;
|
||||
}
|
||||
|
||||
session tx1
|
||||
setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; }
|
||||
step s1 { SELECT; }
|
||||
step refresh { SELECT pgivm.refresh_immv('mv', true); }
|
||||
step check1 {SELECT check_mv();}
|
||||
step c1 { COMMIT; }
|
||||
step mv { SELECT * FROM mv ORDER BY 1,2; SELECT check_mv(); }
|
||||
|
||||
session tx2
|
||||
setup { BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE; }
|
||||
step s2 { SELECT; }
|
||||
step insert { INSERT INTO a VALUES (2); }
|
||||
step check2 {SELECT check_mv(); }
|
||||
step c2 { COMMIT; }
|
||||
|
||||
permutation s1 refresh s2 insert c1 check2 c2 mv
|
||||
permutation s1 refresh s2 c1 insert check2 c2 mv
|
||||
permutation s1 s2 refresh insert c1 check2 c2 mv
|
||||
permutation s1 s2 insert refresh c2 check1 c1 mv
|
||||
permutation s1 s2 refresh c1 insert check2 c2 mv
|
||||
permutation s2 insert s1 refresh c2 check1 c1 mv
|
||||
permutation s2 insert s1 c2 refresh check1 c1 mv
|
||||
permutation s2 s1 insert c2 refresh check1 c1 mv
|
||||
Loading…
Reference in a new issue