| -- MPP-21536: Duplicated rows inserted when ORCA is turned on |
| |
| create schema bfv_dml; |
| set search_path=bfv_dml; |
| |
| -- create test table |
| create table m(); |
| alter table m add column a int; |
| alter table m add column b int; |
| |
| -- generate data for m |
| insert into m select i, i%5 from generate_series(1,10)i; |
| |
| -- INSERT and UPDATE |
| create table yyy(a int, b int) distributed randomly; |
| |
| insert into yyy select a,b from m; |
| select * from yyy order by 1, 2; |
| |
| update yyy set a=m.b from m where m.a=yyy.b; |
| select * from yyy order by 1, 2; |
| |
| drop table yyy; |
| |
| |
| -- UPDATE with different values |
| create table yyy(a int, b int) distributed randomly; |
| |
| insert into yyy select a,b from m; |
| update yyy set b=m.b from m where m.a=yyy.a; |
| select * from yyy order by 1, 2; |
| |
| drop table yyy; |
| |
| |
| -- DELETE |
| create table yyy(a int, b int) distributed randomly; |
| |
| insert into yyy select a,b from m; |
| delete from yyy where a in (select a from m); |
| select * from yyy order by 1, 2; |
| |
| drop table yyy; |
| |
| create table yyy(a int, b int) distributed randomly; |
| insert into yyy select a,b from m; |
| delete from yyy where b in (select a from m); |
| select * from yyy order by 1, 2; |
| |
| drop table yyy; |
| |
| |
| -- Now repeat all the above tests, but using a hacked master-only 'm' table |
| drop table m; |
| |
| set optimizer_enable_master_only_queries=on; |
| |
| |
| -- create master-only table |
| create table m(); |
| set allow_system_table_mods=true; |
| delete from gp_distribution_policy where localoid='m'::regclass; |
| reset allow_system_table_mods; |
| alter table m add column a int; |
| alter table m add column b int; |
| |
| -- generate data for m |
| insert into m select i, i%5 from generate_series(1,10)i; |
| |
| create table zzz(a int primary key, b int) distributed by (a); |
| insert into zzz select a,b from m; |
| select * from zzz order by 1, 2; |
| |
| delete from zzz where a in (select a from m); |
| select * from zzz order by 1, 2; |
| |
| drop table zzz; |
| |
| create table zzz(a int primary key, b int) distributed by (a); |
| |
| insert into zzz select a,b from m; |
| delete from zzz where b in (select a from m); |
| select * from zzz order by 1, 2; |
| |
| drop table zzz; |
| |
| create table zzz(a int primary key, b int) distributed by (a); |
| insert into zzz select a,b from m; |
| |
| -- This update fails with duplicate key error, but it varies which segment |
| -- reports it first, i.e. it varies which row it complaints first. Silence |
| -- that difference in the error DETAIL line |
| \set VERBOSITY terse |
| update zzz set a=m.b from m where m.a=zzz.b; |
| select * from zzz order by 1, 2; |
| |
| drop table zzz; |
| |
| create table zzz(a int primary key, b int) distributed by (a); |
| insert into zzz select a,b from m; |
| update zzz set b=m.b from m where m.a=zzz.a; |
| select * from zzz order by 1, 2; |
| |
| drop table zzz; |
| drop table m; |
| |
| |
| -- MPP-21622 Update with primary key: only sort if the primary key is updated |
| -- |
| -- Aside from testing that bug, this also tests EXPLAIN of an DMLActionExpr |
| -- that ORCA generates for plans that update the primary key. |
| create table update_pk_test (a int primary key, b int) distributed by (a); |
| insert into update_pk_test values(1,1); |
| |
| explain update update_pk_test set b = 5; |
| update update_pk_test set b = 5; |
| select * from update_pk_test order by 1,2; |
| |
| explain update update_pk_test set a = 5; |
| update update_pk_test set a = 5; |
| select * from update_pk_test order by 1,2; |
| |
| |
| -- MPP-22599 DML queries that fallback to planner don't check for updates on |
| -- the distribution key. |
| -- |
| -- So the bug was that if ORCA fell back to the planner, then the usual |
| -- check that prohibits updating the distribution key columns was not |
| -- performed like it should. So the idea of this test is to have an UPDATE |
| -- on distribution key column, with some features in the table or the query, |
| -- such that ORCA cannot produce a plan and it falls back to the Postgres |
| -- planner. |
| set optimizer_trace_fallback = on; |
| |
| -- Subquery that returns a row rather than a single scalar isn't supported |
| -- in ORCA currently, so we can use that to trigger fallback. |
| update update_pk_test set a=1 where row(1,2) = (SELECT 1, 2); |
| select * from update_pk_test order by 1,2; |
| reset optimizer_trace_fallback; |
| |
| |
| -- |
| -- Check that INSERT and DELETE triggers don't fire on UPDATE. |
| -- |
| -- It may seem weird how that could happen, but with ORCA, UPDATEs are |
| -- implemented as a "split update", which is really a DELETE and an INSERT. |
| -- |
| CREATE TABLE bfv_dml_trigger_test (id int4, t text); |
| |
| INSERT INTO bfv_dml_trigger_test VALUES (1, 'foo'); |
| |
| CREATE OR REPLACE FUNCTION bfv_dml_error_func() RETURNS trigger AS |
| $$ |
| BEGIN |
| RAISE EXCEPTION 'trigger was called!'; |
| RETURN NEW; |
| END |
| $$ LANGUAGE 'plpgsql'; |
| |
| CREATE TRIGGER before_trigger BEFORE INSERT or DELETE ON bfv_dml_trigger_test |
| FOR EACH ROW |
| EXECUTE PROCEDURE bfv_dml_error_func(); |
| |
| CREATE TRIGGER after_trigger AFTER INSERT or DELETE ON bfv_dml_trigger_test |
| FOR EACH ROW |
| EXECUTE PROCEDURE bfv_dml_error_func(); |
| |
| UPDATE bfv_dml_trigger_test SET t = 'bar'; |
| UPDATE bfv_dml_trigger_test SET id = id + 1; |
| |
| -- |
| -- Verify that ExecInsert doesn't scribble on the old tuple, when the new |
| -- tuple comes directly from the old table. |
| -- |
| CREATE TABLE execinsert_test (id int4, t text) DISTRIBUTED BY (id); |
| |
| INSERT INTO execinsert_test values (1, 'foo'); |
| |
| -- Insert another identical tuple, but roll it back. If the insertion |
| -- incorrectly modified the xmin on the old tuple, then it will become |
| -- invisible when we roll back. |
| begin; |
| INSERT INTO execinsert_test select * FROM execinsert_test; |
| rollback; |
| select * from execinsert_test; |
| |
| drop table execinsert_test; |
| |
| -- Repeat with a hacked master-only table, just in case the planner decides |
| -- to add a Motion node or something that hides the problem otherwise. |
| |
| CREATE TABLE execinsert_test (id int4, t text) DISTRIBUTED BY (id); |
| set allow_system_table_mods=true; |
| delete from gp_distribution_policy where localoid='execinsert_test'::regclass; |
| reset allow_system_table_mods; |
| |
| INSERT INTO execinsert_test values (1, 'foo'); |
| begin; |
| INSERT INTO execinsert_test select * FROM execinsert_test; |
| rollback; |
| select * from execinsert_test; |
| |
| drop table execinsert_test; |
| |
| -- |
| -- Verify that DELETE properly redistributes in the case of joins |
| -- |
| |
| drop table if exists foo; |
| drop table if exists bar; |
| |
| create table foo (a int, b int); |
| create table bar(a int, b int); |
| insert into foo select generate_series(1,10); |
| insert into bar select generate_series(1,10); |
| -- Previously, table foo is defined as randomly distributed and |
| -- that might lead to flaky result of the explain statement |
| -- since random cost. We set policy to random without move the |
| -- data after data is all inserted. This method can both have |
| -- a random dist table and a stable test result. |
| -- Following cases are using the same skill here. |
| alter table foo set with(REORGANIZE=false) distributed randomly; |
| analyze foo; |
| analyze bar; |
| explain delete from foo using bar where foo.a=bar.a; |
| delete from foo using bar where foo.a=bar.a; |
| select * from foo; |
| drop table foo; |
| drop table bar; |
| |
| create table foo (a int, b int); |
| create table bar(a int, b int); |
| insert into foo select generate_series(1,10); |
| insert into bar select generate_series(1,10); |
| alter table foo set with(REORGANIZE=false) distributed randomly; |
| analyze foo; |
| analyze bar; |
| explain delete from foo using bar where foo.a = bar.a returning foo.*; |
| delete from foo using bar where foo.a = bar.a returning foo.*; |
| select * from foo; |
| drop table foo; |
| drop table bar; |
| |
| create table foo (a int, b int); |
| insert into foo select generate_series(1,10); |
| alter table foo set with(REORGANIZE=false) distributed randomly; |
| analyze foo; |
| explain delete from foo where foo.a=1; |
| delete from foo where foo.a=1; |
| drop table foo; |
| |
| create table foo (a int, b int); |
| create table bar(a int, b int); |
| insert into foo select generate_series(1,10); |
| insert into bar select generate_series(1,10); |
| alter table foo set with(REORGANIZE=false) distributed randomly; |
| analyze foo; |
| analyze bar; |
| explain delete from foo using bar where foo.a=bar.b; |
| delete from foo using bar where foo.a=bar.b; |
| drop table foo; |
| drop table bar; |
| |
| create table foo (a int, b int); |
| insert into foo select generate_series(1,10); |
| alter table foo set with(REORGANIZE=false) distributed randomly; |
| analyze foo; |
| -- Turn off redistribute motion for ORCA just for this case. |
| -- This is to get a broadcast motion over foo_1 so that no |
| -- motion is above the resultrelation foo thus no ExplicitMotion. |
| set optimizer_enable_motion_redistribute = off; |
| explain delete from foo using foo foo_1 where foo_1.a=foo.a; |
| delete from foo using foo foo_1 where foo_1.a=foo.a; |
| reset optimizer_enable_motion_redistribute; |
| drop table foo; |
| |
| create table foo (a int, b int); |
| insert into foo select generate_series(1,10); |
| alter table foo set with(REORGANIZE=false) distributed randomly; |
| analyze foo; |
| explain delete from foo; |
| delete from foo; |
| drop table foo; |
| |
| create table foo (a int, b int); |
| create table bar(a int, b int); |
| insert into foo select generate_series(1,10); |
| insert into bar select generate_series(1,10); |
| alter table foo set with(REORGANIZE=false) distributed randomly; |
| alter table bar set with(REORGANIZE=false) distributed randomly; |
| analyze foo; |
| analyze bar; |
| explain delete from foo using bar; |
| delete from foo using bar; |
| drop table foo; |
| drop table bar; |
| |
| create table foo (a int, b int); |
| create table bar(a int, b int); |
| insert into bar select i, i from generate_series(1, 1000)i; |
| insert into foo select i,i from generate_series(1, 10)i; |
| alter table foo set with(REORGANIZE=false) distributed randomly; |
| alter table bar set with(REORGANIZE=false) distributed randomly; |
| analyze foo; |
| analyze bar; |
| set optimizer_enable_motion_redistribute=off; |
| explain delete from foo using bar where foo.b=bar.b; |
| delete from foo using bar where foo.b=bar.b; |
| drop table foo; |
| drop table bar; |
| reset optimizer_enable_motion_redistribute; |
| |
| create table foo (a int, b int) distributed randomly; |
| create table bar (a int, b int) distributed randomly; |
| insert into foo (a, b) values (1, 2); |
| explain insert into bar select * from foo; |
| insert into bar select * from foo; |
| select * from bar; |
| drop table foo; |
| drop table bar; |
| |
| create table foo (a int, b int) distributed randomly; |
| create table bar (a int, b int) distributed randomly; |
| insert into foo (a, b) values (1, 2); |
| insert into bar (a, b) values (1, 2); |
| explain update foo set a=4 from bar where foo.a=bar.a; |
| update foo set a=4 from bar where foo.a=bar.a; |
| select * from foo; |
| drop table foo; |
| drop table bar; |
| |
| create table foo (a int, b int) distributed randomly; |
| create table bar (a int, b int) distributed randomly; |
| create table jazz (a int, b int) distributed randomly; |
| insert into foo (a, b) values (1, 2); |
| insert into bar (a, b) values (1, 2); |
| insert into jazz (a, b) values (1, 2); |
| explain insert into foo select bar.a from bar, jazz where bar.a=jazz.a; |
| insert into foo select bar.a from bar, jazz where bar.a=jazz.a; |
| select * from foo; |
| drop table foo; |
| drop table bar; |
| drop table jazz; |
| |
| create table foo (a int); |
| create table bar (b int); |
| insert into foo select i from generate_series(1, 10)i; |
| insert into bar select i from generate_series(1, 10)i; |
| alter table foo set with(REORGANIZE=false) distributed randomly; |
| alter table bar set with(REORGANIZE=false) distributed randomly; |
| analyze foo; |
| analyze bar; |
| explain delete from foo using (select a from foo union all select b from bar) v; |
| delete from foo using (select a from foo union all select b from bar) v; |
| select * from foo; |
| drop table foo; |
| drop table bar; |
| |
| -- This test is to verify ORCA can generate plans with empty |
| -- target lists. This can happen when inserting rows with no |
| -- columns into a table with no columns |
| create table test(); |
| explain (analyze, costs off, timing off, summary off) insert into test default values; |
| |
| -- Test delete on partition table with dropped/added columns |
| CREATE TABLE part ( |
| a int, |
| b int, |
| c text, |
| d numeric) |
| DISTRIBUTED BY (b) |
| partition by range(a) ( |
| start(1) end(6) every(2), |
| default partition def); |
| alter table part add column e int; |
| insert into part select i, i, 'abc', i*1.01,i from generate_series(1,10)i; |
| alter table part drop column b; |
| alter table part set WITH (reorganize=true) distributed by (e); |
| -- test delete with dropped column |
| explain delete from part where d>9; |
| delete from part where d>9; |
| select count(*) from part; |
| -- test delete with added partition key |
| explain delete from part where e=3; |
| delete from part where e=3; |
| select count(*) from part; |
| -- test delete from default partition |
| explain delete from part where a=8; |
| delete from part where a=8; |
| select count(*) from part; |
| |
| DROP TABLE IF EXISTS part; |
| CREATE TABLE part ( |
| a int, |
| b int, |
| partkey int, |
| c text, |
| d numeric) |
| DISTRIBUTED BY (b) |
| partition by range(partkey) ( |
| start(1) end(6) every(2), |
| default partition def); |
| alter table part add column e int; |
| insert into part select i, i, i, 'abc', i*1.01,i from generate_series(1,10)i; |
| alter table part drop column b; |
| alter table part set WITH (reorganize=true) distributed by (e); |
| -- test delete with column order change |
| explain delete from part where d>9; |
| delete from part where d>9; |
| select count(*) from part; |
| |
| -- Test delete on mid-level partitions. Ensure Orca properly handles tuple routing |
| create table deep_part ( |
| i int, |
| j int, |
| k int, |
| s char(5) |
| ) distributed by (i) partition by list(s) subpartition by range (j) subpartition template ( |
| start(1) end(3) every(1) |
| ) ( |
| partition p1 |
| values |
| ('A'), |
| partition p2 |
| values |
| ('B') |
| ); |
| |
| insert into deep_part values (1,1,1,'A'); |
| delete from deep_part_1_prt_p1 where j=1; |