未验证 提交 d6b1289f 编写于 作者: T Tang Pengzhou 提交者: GitHub

Disable Current Of for replicated table (#6407)

* Disable Current Of for replicated table

Let's list the plans using CURRENT OF:

    explain delete from t1 WHERE CURRENT OF c1;
                            QUERY PLAN
    -----------------------------------------------------------
     Delete on t1  (cost=0.00..100.01 rows=1 width=10)
       ->  Tid Scan on t1  (cost=0.00..100.01 rows=1 width=10)
             Output: ctid, gp_segment_id
             TID Cond: CURRENT OF c1
             Filter: CURRENT OF c1

    explain UPDATE r1 SET b = 3 WHERE CURRENT OF c1;
                            QUERY PLAN
    -----------------------------------------------------------
     Update on r1  (cost=0.00..100.01 rows=1 width=18)
       ->  Tid Scan on r1  (cost=0.00..100.01 rows=1 width=18)
             Output: ctid, gp_segment_id
             TID Cond: CURRENT OF c1
             Filter: CURRENT OF c1

(ctid + gp_segment_id) can identify a unique row for hash distributed
table or randomly distributed table, but for replicated table, it can
only identify a row in one replica, so in this case other replicas
are not updated or deleted properly. There is no proper way to let
CURRENT OF work fine for replicated table, so just disable it for now.

Updatable view works fine now because all the operations are designed
to executed locally, rows of each replica are never flowed to other
segments and each replica have the same data flow. For example:
     create view v_r2 as select * from r2 where c2 = 3;

     explain update v_r2 set c2 = 4 from p1 where p1.c2=v_r2.c2;
                            QUERY PLAN
    -----------------------------------------------------------
     Update on r2
       ->  Nested Loop
             ->  Seq Scan on r2
                   Filter: (c2 = 3)
             ->  Materialize
                   ->  Broadcast Motion 3:3
                         ->  Seq Scan on p1
                               Filter: (c2 = 3)
As the plan shows, p1 is broadcasted, so all replicas of replicated
table operate locally
上级 e648cf45
......@@ -1921,7 +1921,7 @@ getLockedRefname(ParseState *pstate, const char *refname)
* isSimplyUpdatableRelation
*
* The oid must reference a normal, heap relation. This disallows
* AO, AO/CO, external tables, views, etc.
* AO, AO/CO, external tables, views, replicated table etc.
*
* If 'noerror' is true, function returns true/false. If 'noerror'
* is false, throws an error if the relation is not simply updatable.
......@@ -1980,6 +1980,23 @@ isSimplyUpdatableRelation(Oid relid, bool noerror)
return_value = false;
break;
}
/*
* A row in replicated table cannot be identified by (ctid + gp_segment_id)
* in all replicas, for each row replica, the gp_segment_id is different,
* the ctid is also not guaranteed to be the same, so it's not simply
* updateable for CURRENT OF.
*/
if (GpPolicyIsReplicated(rel->rd_cdbpolicy))
{
if (!noerror)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("\"%s\" is not simply updatable",
RelationGetRelationName(rel))));
return_value = false;
break;
}
} while (0);
relation_close(rel, NoLock);
......
......@@ -544,7 +544,68 @@ select * from bar where exists (select * from foo);
1 | 2
(2 rows)
------
-- Test Current Of is disabled for replicated table
------
begin;
declare c1 cursor for select * from foo;
fetch 1 from c1;
x | y
---+---
1 | 1
(1 row)
delete from foo where current of c1;
ERROR: "foo" is not simply updatable
abort;
begin;
declare c1 cursor for select * from foo;
fetch 1 from c1;
x | y
---+---
1 | 1
(1 row)
update foo set y = 1 where current of c1;
ERROR: "foo" is not simply updatable
abort;
-----
-- Test updatable view works for replicated table
----
truncate foo;
truncate bar;
insert into foo values (1, 1);
insert into foo values (2, 2);
insert into bar values (1, 1);
create view v_foo as select * from foo where y = 1;
begin;
update v_foo set y = 2;
select * from gp_dist_random('foo');
x | y
---+---
2 | 2
1 | 2
2 | 2
1 | 2
2 | 2
1 | 2
(6 rows)
abort;
update v_foo set y = 3 from bar where bar.y = v_foo.y;
select * from gp_dist_random('foo');
x | y
---+---
2 | 2
1 | 3
2 | 2
1 | 3
2 | 2
1 | 3
(6 rows)
drop schema rpt cascade;
NOTICE: drop cascades to 2 other objects
NOTICE: drop cascades to 3 other objects
DETAIL: drop cascades to table foo
drop cascades to table bar
drop cascades to view v_foo
......@@ -271,4 +271,36 @@ select * from foo;
insert into foo values (1, 1), (2, 1);
select * from bar where exists (select * from foo);
------
-- Test Current Of is disabled for replicated table
------
begin;
declare c1 cursor for select * from foo;
fetch 1 from c1;
delete from foo where current of c1;
abort;
begin;
declare c1 cursor for select * from foo;
fetch 1 from c1;
update foo set y = 1 where current of c1;
abort;
-----
-- Test updatable view works for replicated table
----
truncate foo;
truncate bar;
insert into foo values (1, 1);
insert into foo values (2, 2);
insert into bar values (1, 1);
create view v_foo as select * from foo where y = 1;
begin;
update v_foo set y = 2;
select * from gp_dist_random('foo');
abort;
update v_foo set y = 3 from bar where bar.y = v_foo.y;
select * from gp_dist_random('foo');
drop schema rpt cascade;
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册