diff options
| author | Tom Lane | 2007-10-24 18:37:09 +0000 |
|---|---|---|
| committer | Tom Lane | 2007-10-24 18:37:09 +0000 |
| commit | c29a9c37bf6bdaaaa65ccbcd4c69c596691134e1 (patch) | |
| tree | c7df7fd2c22d5007ff6901800714d93bc4ce8a4c /src/test | |
| parent | 9226ba817b19999d51d39a0a2bde810160d0cf24 (diff) | |
Fix UPDATE/DELETE WHERE CURRENT OF to support repeated update and update-
then-delete on the current cursor row. The basic fix is that nodeTidscan.c
has to apply heap_get_latest_tid() to the current-scan-TID obtained from the
cursor query; this ensures we get the latest row version to work with.
However, since that only works if the query plan is a TID scan, we also have
to hack the planner to make sure only that type of plan will be selected.
(Formerly, the planner might decide to apply a seqscan if the table is very
small. This change is probably a Good Thing anyway, since it's hard to see
how a seqscan could really win.) That means the execQual.c code to support
CurrentOfExpr as a regular expression type is dead code, so replace it with
just an elog(). Also, add regression tests covering these cases. Note
that the added tests expose the fact that re-fetching an updated row
misbehaves if the cursor used FOR UPDATE. That's an independent bug that
should be fixed later. Per report from Dharmendra Goyal.
Diffstat (limited to 'src/test')
| -rw-r--r-- | src/test/regress/expected/portals.out | 133 | ||||
| -rw-r--r-- | src/test/regress/sql/portals.sql | 40 |
2 files changed, 173 insertions, 0 deletions
diff --git a/src/test/regress/expected/portals.out b/src/test/regress/expected/portals.out index 3638664b1bb..b6673073cdf 100644 --- a/src/test/regress/expected/portals.out +++ b/src/test/regress/expected/portals.out @@ -982,6 +982,139 @@ SELECT * FROM uctest; 8 | one (2 rows) +-- Check repeated-update and update-then-delete cases +BEGIN; +DECLARE c1 CURSOR FOR SELECT * FROM uctest; +FETCH c1; + f1 | f2 +----+------- + 3 | three +(1 row) + +UPDATE uctest SET f1 = f1 + 10 WHERE CURRENT OF c1; +SELECT * FROM uctest; + f1 | f2 +----+------- + 8 | one + 13 | three +(2 rows) + +UPDATE uctest SET f1 = f1 + 10 WHERE CURRENT OF c1; +SELECT * FROM uctest; + f1 | f2 +----+------- + 8 | one + 23 | three +(2 rows) + +-- insensitive cursor should not show effects of updates or deletes +FETCH RELATIVE 0 FROM c1; + f1 | f2 +----+------- + 3 | three +(1 row) + +DELETE FROM uctest WHERE CURRENT OF c1; +SELECT * FROM uctest; + f1 | f2 +----+----- + 8 | one +(1 row) + +DELETE FROM uctest WHERE CURRENT OF c1; -- no-op +SELECT * FROM uctest; + f1 | f2 +----+----- + 8 | one +(1 row) + +UPDATE uctest SET f1 = f1 + 10 WHERE CURRENT OF c1; -- no-op +SELECT * FROM uctest; + f1 | f2 +----+----- + 8 | one +(1 row) + +FETCH RELATIVE 0 FROM c1; + f1 | f2 +----+------- + 3 | three +(1 row) + +ROLLBACK; +SELECT * FROM uctest; + f1 | f2 +----+------- + 3 | three + 8 | one +(2 rows) + +BEGIN; +DECLARE c1 CURSOR FOR SELECT * FROM uctest FOR UPDATE; +FETCH c1; + f1 | f2 +----+------- + 3 | three +(1 row) + +UPDATE uctest SET f1 = f1 + 10 WHERE CURRENT OF c1; +SELECT * FROM uctest; + f1 | f2 +----+------- + 8 | one + 13 | three +(2 rows) + +UPDATE uctest SET f1 = f1 + 10 WHERE CURRENT OF c1; +SELECT * FROM uctest; + f1 | f2 +----+------- + 8 | one + 23 | three +(2 rows) + +-- sensitive cursor should show effects of updates or deletes +-- XXX current behavior is WRONG +FETCH RELATIVE 0 FROM c1; + f1 | f2 +----+----- + 8 | one +(1 row) + +DELETE FROM uctest WHERE CURRENT OF c1; +SELECT * FROM uctest; + f1 | f2 +----+------- + 23 | three +(1 row) + +DELETE FROM uctest WHERE CURRENT OF c1; -- no-op +SELECT * FROM uctest; + f1 | f2 +----+------- + 23 | three +(1 row) + +UPDATE uctest SET f1 = f1 + 10 WHERE CURRENT OF c1; -- no-op +SELECT * FROM uctest; + f1 | f2 +----+------- + 23 | three +(1 row) + +FETCH RELATIVE 0 FROM c1; + f1 | f2 +----+---- +(0 rows) + +ROLLBACK; +SELECT * FROM uctest; + f1 | f2 +----+------- + 3 | three + 8 | one +(2 rows) + -- Check inheritance cases CREATE TEMP TABLE ucchild () inherits (uctest); INSERT INTO ucchild values(100, 'hundred'); diff --git a/src/test/regress/sql/portals.sql b/src/test/regress/sql/portals.sql index 382a28c4e30..bdf5956d69c 100644 --- a/src/test/regress/sql/portals.sql +++ b/src/test/regress/sql/portals.sql @@ -349,6 +349,46 @@ SELECT * FROM uctest; COMMIT; SELECT * FROM uctest; +-- Check repeated-update and update-then-delete cases +BEGIN; +DECLARE c1 CURSOR FOR SELECT * FROM uctest; +FETCH c1; +UPDATE uctest SET f1 = f1 + 10 WHERE CURRENT OF c1; +SELECT * FROM uctest; +UPDATE uctest SET f1 = f1 + 10 WHERE CURRENT OF c1; +SELECT * FROM uctest; +-- insensitive cursor should not show effects of updates or deletes +FETCH RELATIVE 0 FROM c1; +DELETE FROM uctest WHERE CURRENT OF c1; +SELECT * FROM uctest; +DELETE FROM uctest WHERE CURRENT OF c1; -- no-op +SELECT * FROM uctest; +UPDATE uctest SET f1 = f1 + 10 WHERE CURRENT OF c1; -- no-op +SELECT * FROM uctest; +FETCH RELATIVE 0 FROM c1; +ROLLBACK; +SELECT * FROM uctest; + +BEGIN; +DECLARE c1 CURSOR FOR SELECT * FROM uctest FOR UPDATE; +FETCH c1; +UPDATE uctest SET f1 = f1 + 10 WHERE CURRENT OF c1; +SELECT * FROM uctest; +UPDATE uctest SET f1 = f1 + 10 WHERE CURRENT OF c1; +SELECT * FROM uctest; +-- sensitive cursor should show effects of updates or deletes +-- XXX current behavior is WRONG +FETCH RELATIVE 0 FROM c1; +DELETE FROM uctest WHERE CURRENT OF c1; +SELECT * FROM uctest; +DELETE FROM uctest WHERE CURRENT OF c1; -- no-op +SELECT * FROM uctest; +UPDATE uctest SET f1 = f1 + 10 WHERE CURRENT OF c1; -- no-op +SELECT * FROM uctest; +FETCH RELATIVE 0 FROM c1; +ROLLBACK; +SELECT * FROM uctest; + -- Check inheritance cases CREATE TEMP TABLE ucchild () inherits (uctest); INSERT INTO ucchild values(100, 'hundred'); |
