Test some more cases with partitioned tables in EvalPlanQual.
authorTom Lane <tgl@sss.pgh.pa.us>
Tue, 9 Apr 2019 15:42:53 +0000 (11:42 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Tue, 9 Apr 2019 15:43:03 +0000 (11:43 -0400)
We weren't testing anything involving EPQ on UPDATEs that move tuples
into different partitions.  Depending on the implementation,
it might be that these cases aren't actually very interesting ...
but given our thin coverage of EPQ in general, I think it's a good
idea to have a test case.

Amit Langote, minor tweak by me

Discussion: https://postgr.es/m/7889df35-ad1a-691a-00e3-4d4b18f364e3@lab.ntt.co.jp

src/test/isolation/expected/eval-plan-qual.out
src/test/isolation/specs/eval-plan-qual.spec

index 703f41006849889520bb0b79bbcb4d8e319fac8a..5bf6ec1c273423a0704acb631e83df6258140b40 100644 (file)
@@ -641,3 +641,55 @@ step complexpartupdate:
 step c1: COMMIT;
 step complexpartupdate: <... completed>
 step c2: COMMIT;
+
+starting permutation: simplepartupdate_route1to2 complexpartupdate_route_err1 c1 c2
+step simplepartupdate_route1to2: 
+       update parttbl set a = 2 where c = 1 returning *;
+
+a              b              c              
+
+2              1              1              
+step complexpartupdate_route_err1: 
+       with u as (update another_parttbl set a = 1 returning another_parttbl.*)
+       update parttbl p set a = u.a from u where p.a = u.a and p.c = 1 returning p.*;
+ <waiting ...>
+step c1: COMMIT;
+step complexpartupdate_route_err1: <... completed>
+error in steps c1 complexpartupdate_route_err1: ERROR:  tuple to be locked was already moved to another partition due to concurrent update
+step c2: COMMIT;
+
+starting permutation: simplepartupdate_noroute complexpartupdate_route c1 c2
+step simplepartupdate_noroute: 
+       update parttbl set b = 2 where c = 1 returning *;
+
+a              b              c              
+
+1              2              1              
+step complexpartupdate_route: 
+       with u as (update another_parttbl set a = 1 returning another_parttbl.*)
+       update parttbl p set a = p.b from u where p.a = u.a and p.c = 1 returning p.*;
+ <waiting ...>
+step c1: COMMIT;
+step complexpartupdate_route: <... completed>
+a              b              c              
+
+2              2              1              
+step c2: COMMIT;
+
+starting permutation: simplepartupdate_noroute complexpartupdate_doesnt_route c1 c2
+step simplepartupdate_noroute: 
+       update parttbl set b = 2 where c = 1 returning *;
+
+a              b              c              
+
+1              2              1              
+step complexpartupdate_doesnt_route: 
+       with u as (update another_parttbl set a = 1 returning another_parttbl.*)
+       update parttbl p set a = 3 - p.b from u where p.a = u.a and p.c = 1 returning p.*;
+ <waiting ...>
+step c1: COMMIT;
+step complexpartupdate_doesnt_route: <... completed>
+a              b              c              
+
+1              2              1              
+step c2: COMMIT;
index 4744f558b0f412a0706b42f2c6ee7edab1f9fae1..f35a64ef63ea79ff84e7da640c13c0f56216cc43 100644 (file)
@@ -33,9 +33,15 @@ setup
  CREATE TABLE jointest AS SELECT generate_series(1,10) AS id, 0 AS data;
  CREATE INDEX ON jointest(id);
 
- CREATE TABLE parttbl (a int) PARTITION BY LIST (a);
+ CREATE TABLE parttbl (a int, b int, c int) PARTITION BY LIST (a);
  CREATE TABLE parttbl1 PARTITION OF parttbl FOR VALUES IN (1);
- INSERT INTO parttbl VALUES (1);
+ CREATE TABLE parttbl2 PARTITION OF parttbl FOR VALUES IN (2);
+ INSERT INTO parttbl VALUES (1, 1, 1);
+
+ CREATE TABLE another_parttbl (a int, b int, c int) PARTITION BY LIST (a);
+ CREATE TABLE another_parttbl1 PARTITION OF another_parttbl FOR VALUES IN (1);
+ CREATE TABLE another_parttbl2 PARTITION OF another_parttbl FOR VALUES IN (2);
+ INSERT INTO another_parttbl VALUES (1, 1, 1);
 }
 
 teardown
@@ -46,6 +52,7 @@ teardown
  DROP TABLE p CASCADE;
  DROP TABLE table_a, table_b, jointest;
  DROP TABLE parttbl;
+ DROP TABLE another_parttbl;
 }
 
 session "s1"
@@ -148,6 +155,16 @@ step "simplepartupdate"    {
        update parttbl set a = a;
 }
 
+# test scenarios where update may cause row movement
+
+step "simplepartupdate_route1to2" {
+       update parttbl set a = 2 where c = 1 returning *;
+}
+
+step "simplepartupdate_noroute" {
+       update parttbl set b = 2 where c = 1 returning *;
+}
+
 
 session "s2"
 setup          { BEGIN ISOLATION LEVEL READ COMMITTED; }
@@ -190,6 +207,21 @@ step "complexpartupdate"   {
        update parttbl set a = u.a from u;
 }
 
+step "complexpartupdate_route_err1" {
+       with u as (update another_parttbl set a = 1 returning another_parttbl.*)
+       update parttbl p set a = u.a from u where p.a = u.a and p.c = 1 returning p.*;
+}
+
+step "complexpartupdate_route" {
+       with u as (update another_parttbl set a = 1 returning another_parttbl.*)
+       update parttbl p set a = p.b from u where p.a = u.a and p.c = 1 returning p.*;
+}
+
+step "complexpartupdate_doesnt_route" {
+       with u as (update another_parttbl set a = 1 returning another_parttbl.*)
+       update parttbl p set a = 3 - p.b from u where p.a = u.a and p.c = 1 returning p.*;
+}
+
 # Use writable CTEs to create self-updated rows, that then are
 # (updated|deleted). The *fail versions of the tests additionally
 # perform an update, via a function, in a different command, to test
@@ -278,3 +310,6 @@ permutation "wrjt" "selectresultforupdate" "c2" "c1"
 permutation "wrtwcte" "multireadwcte" "c1" "c2"
 
 permutation "simplepartupdate" "complexpartupdate" "c1" "c2"
+permutation "simplepartupdate_route1to2" "complexpartupdate_route_err1" "c1" "c2"
+permutation "simplepartupdate_noroute" "complexpartupdate_route" "c1" "c2"
+permutation "simplepartupdate_noroute" "complexpartupdate_doesnt_route" "c1" "c2"