summaryrefslogtreecommitdiff
path: root/src/test
diff options
context:
space:
mode:
authorTom Lane2007-10-24 18:37:09 +0000
committerTom Lane2007-10-24 18:37:09 +0000
commitc29a9c37bf6bdaaaa65ccbcd4c69c596691134e1 (patch)
treec7df7fd2c22d5007ff6901800714d93bc4ce8a4c /src/test
parent9226ba817b19999d51d39a0a2bde810160d0cf24 (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.out133
-rw-r--r--src/test/regress/sql/portals.sql40
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');