blob: f213deb2840d4305fece4bcf7889f4c71171c4fc [file] [log] [blame]
-- turn off autostats so we don't have to worry about the logging of the autostat queries
set gp_autostats_mode = None;
-- create needed tables (in a transaction, for speed)
begin;
create table direct_test
(
key int NULL,
value varchar(50) NULL
)
distributed by (key);
create table direct_test_two_column
(
key1 int NULL,
key2 int NULL,
value varchar(50) NULL
)
distributed by (key1, key2);
create table direct_test_bitmap as select '2008-02-01'::DATE AS DT,
case when j <= 996
then 0
when j<= 998 then 2
when j<=999 then 3
when i%10000 < 9000 then 4
when i%10000 < 9800 then 5
when i % 10000 <= 9998 then 5 else 6
end as ind,
(i*1017-j)::bigint as s from generate_series(1,10) i, generate_series(1,10) j distributed by (dt);
create index direct_test_bitmap_idx on direct_test_bitmap using bitmap (ind, dt);
CREATE TABLE direct_test_partition (trans_id int, date date, amount decimal(9,2), region text) DISTRIBUTED BY (trans_id) PARTITION BY RANGE (date) (START (date '2008-01-01') INCLUSIVE END (date '2009-01-01') EXCLUSIVE EVERY (INTERVAL '1month') );
create unique index direct_test_uk on direct_test_partition(trans_id,date);
create table direct_test_range_partition (a int, b int, c int, d int) distributed by (a) partition by range(d) (start(1) end(10) every(1));
insert into direct_test_range_partition select i, i+1, i+2, i+3 from generate_series(1, 2) i;
commit;
-- enable printing of printing info
set test_print_direct_dispatch_info=on;
-- Constant single-row insert, one column in distribution
-- DO direct dispatch
insert into direct_test values (100, 'cow');
-- verify
select * from direct_test order by key, value;
-- Constant single-row update, one column in distribution
-- DO direct dispatch
-- Known_opt_diff: MPP-21346
update direct_test set value = 'horse' where key = 100;
-- verify
select * from direct_test order by key, value;
-- Constant single-row delete, one column in distribution
-- DO direct dispatch
-- Known_opt_diff: MPP-21346
delete from direct_test where key = 100;
-- verify
select * from direct_test order by key, value;
-- Constant single-row insert, one column in distribution
-- DO direct dispatch
insert into direct_test values (NULL, 'cow');
-- verify
select * from direct_test order by key, value;
-- DELETE with an IS NULL predicate
-- DO direct dispatch
delete from direct_test where key is null;
-- Same single-row insert as above, but with DEFAULT instead of an explicit values.
-- DO direct dispatch
insert into direct_test values (default, 'cow');
-- verify
select * from direct_test order by key, value;
-- Constant single-row insert, two columns in distribution
-- DO direct dispatch
-- Known_opt_diff: MPP-21346
insert into direct_test_two_column values (100, 101, 'cow');
-- verify
select * from direct_test_two_column order by key1, key2, value;
-- Constant single-row update, two columns in distribution
-- DO direct dispatch
-- Known_opt_diff: MPP-21346
update direct_test_two_column set value = 'horse' where key1 = 100 and key2 = 101;
-- verify
select * from direct_test_two_column order by key1, key2, value;
-- Constant single-row delete, two columns in distribution
-- DO direct dispatch
delete from direct_test_two_column where key1 = 100 and key2 = 101;
-- verify
select * from direct_test_two_column order by key1, key2, value;
-- expression single-row insert
-- DO direct dispatch
insert into direct_test (key, value) values ('123',123123);
insert into direct_test (key, value) values (sqrt(100*10*10),123123);
--
-- should get 100 and 123 as the values
--
select * from direct_test where value = '123123' order by key;
delete from direct_test where value = '123123';
--------------------------------------------------------------------------------
-- Multiple row update, where clause lists multiple values which hash differently so no direct dispatch
--
-- note that if the hash function for values changes then certain segment configurations may actually
-- hash all these values to the same content! (and so test would change)
--
update direct_test set value = 'pig' where key in (1,2,3,4,5);
update direct_test_two_column set value = 'pig' where key1 = 100 and key2 in (1,2,3,4);
update direct_test_two_column set value = 'pig' where key1 in (100,101,102,103,104) and key2 in (1);
update direct_test_two_column set value = 'pig' where key1 in (100,101) and key2 in (1,2);
-- Multiple row update, where clause lists values which all hash to same segment
-- DO direct dispatch
-- CAN'T IMPLEMENT THIS TEST BECAUSE THE # of segments changes again (unless we use a # of segments function, and exploit the simple nature of int4 hashing -- can we do that?)
------------------------------
-- Transaction cases
--
-- note that single-row insert can happen BUT DTM will always go to all contents
--
begin;
insert into direct_test values (1,100);
rollback;
begin;
insert into direct_test values (1,100);
insert into direct_test values (2,100);
insert into direct_test values (3,100);
rollback;
-------------------
-- MPP-7634: bitmap index scan
--
-- Known_opt_diff: MPP-21346
select count(*) from direct_test_bitmap where dt='2008-02-05';
-- Known_opt_diff: MPP-21346
select count(*) from direct_test_bitmap where dt='2008-02-01';
----------------------------------------------------------------------------------
-- MPP-7637: partitioned table
--
insert into direct_test_partition values (1,'2008-01-02',1,'usa');
select * from direct_test_partition where trans_id =1;
----------------------------------------------------------------------------------
-- MPP-7638: range table partition
--
-- Known_opt_diff: MPP-21346
select count(*) from direct_test_range_partition where a =1;
----------------------------------------------------------------------------------
-- Prepared statements
-- do same as above ones but using prepared statements, verify data goes to the right spot
prepare test_insert (int) as insert into direct_test values ($1,100);
execute test_insert(1);
execute test_insert(2);
select * from direct_test;
prepare test_update (int) as update direct_test set value = 'boo' where key = $1;
-- Known_opt_diff: MPP-21346
execute test_update(2);
select * from direct_test;
------------------------
-- A subquery
--
set test_print_direct_dispatch_info=off;
CREATE TEMP TABLE direct_dispatch_foo (id integer) DISTRIBUTED BY (id);
CREATE TEMP TABLE direct_dispatch_bar (id1 integer, id2 integer) DISTRIBUTED by (id1);
INSERT INTO direct_dispatch_foo VALUES (1);
INSERT INTO direct_dispatch_bar VALUES (1, 1);
INSERT INTO direct_dispatch_bar VALUES (2, 2);
INSERT INTO direct_dispatch_bar VALUES (3, 1);
set test_print_direct_dispatch_info=on;
-- Known_opt_diff: MPP-21346
SELECT * FROM direct_dispatch_foo WHERE id IN
(SELECT id2 FROM (SELECT DISTINCT id1, id2 FROM direct_dispatch_bar WHERE direct_dispatch_bar.id1 = 1) AS s) ORDER BY 1;
--
-- this one will NOT do direct dispatch because it is a many slice query and those are disabled right now
SELECT * FROM direct_dispatch_foo WHERE id IN
(SELECT id2 FROM (SELECT id1, id2 FROM direct_dispatch_bar WHERE direct_dispatch_bar.id1 = 1 UNION
SELECT id1, id2 FROM direct_dispatch_bar WHERE direct_dispatch_bar.id1 = 2) AS s) ORDER BY 1;
-- simple one using an expression on the variable
SELECT * from direct_dispatch_foo WHERE id * id = 1;
SELECT * from direct_dispatch_foo WHERE id * id = 1 OR id = 1;
SELECT * from direct_dispatch_foo where id * id = 1 AND id = 1;
-- main plan is direct dispatch and also has init plans
update direct_dispatch_bar set id2 = 1 where id1 = 1 and exists (select * from direct_dispatch_foo where id = 2);
-- init plan to see how transaction escalation happens
-- Known_opt_diff: MPP-21346
delete from direct_dispatch_foo where id = (select max(id2) from direct_dispatch_bar where id1 = 5);
-- Known_opt_diff: MPP-21346
delete from direct_dispatch_foo where id * id = (select max(id2) from direct_dispatch_bar where id1 = 5) AND id = 3;
-- Known_opt_diff: MPP-21346
delete from direct_dispatch_foo where id * id = (select max(id2) from direct_dispatch_bar) AND id = 3;
-- tests with subplans (MPP-22019)
CREATE TABLE MPP_22019_a ( i INT, j INT) DISTRIBUTED BY (i);
INSERT INTO MPP_22019_a (
SELECT i, i * i FROM generate_series(1, 10) AS i);
CREATE TABLE MPP_22019_b (i INT, j INT) DISTRIBUTED BY (i);
INSERT INTO MPP_22019_b (SELECT i, i * i FROM generate_series(1, 10) AS i);
EXPLAIN SELECT a.* FROM MPP_22019_a a INNER JOIN MPP_22019_b b ON a.i = b.i WHERE a.j NOT IN (SELECT j FROM MPP_22019_a a2 where a2.j = b.j) and a.i = 1;
SELECT a.* FROM MPP_22019_a a INNER JOIN MPP_22019_b b ON a.i = b.i WHERE a.j NOT IN (SELECT j FROM MPP_22019_a a2 where a2.j = b.j) and a.i = 1;
SELECT a.* FROM MPP_22019_a a WHERE a.j NOT IN (SELECT j FROM MPP_22019_a a2 where a2.j = a.j) and a.i = 1;
--
-- Test direct dispatch with volatile functions, and nextval().
--
-- Simple table.
create table ddtesttab (i int, j int, k int8) distributed by (k);
create sequence ddtestseq cache 1;
insert into ddtesttab values (1, 1, 5);
insert into ddtesttab values (1, 1, 5 + random()); -- volatile expression as distribution key
insert into ddtesttab values (1, 1, nextval('ddtestseq'));
insert into ddtesttab values (1, 1, 5 + nextval('ddtestseq'));
drop table ddtesttab;
-- Partitioned table, with mixed distribution keys.
create table ddtesttab (i int, j int, k int8) distributed by (i) partition by
range(k)
(start(1) end(20) every(10));
insert into ddtesttab values (1, 1, 5);
insert into ddtesttab values (1, 1, 5 + random()); -- volatile expression as distribution key
insert into ddtesttab values (1, 1, nextval('ddtestseq'));
insert into ddtesttab values (1, 1, 5 + nextval('ddtestseq'));
-- One partition is randomly distributed, while others are distributed by key.
alter table ddtesttab_1_prt_2 set distributed randomly;
insert into ddtesttab values (1, 1, 5);
insert into ddtesttab values (1, 1, 5 + random()); -- volatile expression as distribution key
insert into ddtesttab values (1, 1, nextval('ddtestseq'));
insert into ddtesttab values (1, 1, 5 + nextval('ddtestseq'));
drop table ddtesttab;
drop sequence ddtestseq;
-- Test prepare statement will choose custom plan instead of generic plan when
-- considering no direct dispatch cost.
create table test_prepare(i int, j int);
-- insert case
prepare p1 as insert into test_prepare values($1, 1);
execute p1(1);
execute p1(1);
execute p1(1);
execute p1(1);
execute p1(1);
-- the first 5 execute will always use custom plan, focus on the 6th one.
execute p1(1);
-- update case
prepare p2 as update test_prepare set j =2 where i =$1;
execute p2(1);
execute p2(1);
execute p2(1);
execute p2(1);
execute p2(1);
execute p2(1);
-- select case
prepare p3 as select * from test_prepare where i =$1;
execute p3(1);
execute p3(1);
execute p3(1);
execute p3(1);
execute p3(1);
execute p3(1);
drop table test_prepare;
-- Tests to check direct dispatch if the table is randomly distributed and the
-- filter has condition on gp_segment_id
-- NOTE: Only EXPLAIN query included, output of SELECT query is not shown.
-- Since the table is distributed randomly, the output of SELECT query
-- will differ everytime new table is created, and hence the during comparision
-- the tests will fail.
drop table if exists bar_randDistr;
create table bar_randDistr(col1 int, col2 int) distributed randomly;
insert into bar_randDistr select i,i*2 from generate_series(1, 10)i;
-- Case 1 : simple conditions on gp_segment_id
explain (costs off) select gp_segment_id, * from bar_randDistr where gp_segment_id=0;
explain (costs off) select gp_segment_id, * from bar_randDistr where gp_segment_id=1 or gp_segment_id=2;
explain (costs off) select gp_segment_id, count(*) from bar_randDistr group by gp_segment_id;
-- Case2: Conjunction scenario with filter condition on gp_segment_id and column
explain (costs off) select gp_segment_id, * from bar_randDistr where gp_segment_id=0 and col1 between 1 and 10;
-- Case3: Disjunction scenario with filter condition on gp_segment_id and column
explain (costs off) select gp_segment_id, * from bar_randDistr where gp_segment_id=1 or (col1=6 and gp_segment_id=2);
-- Case4: Scenario with constant/variable column and constant/variable gp_segment_id
explain (costs off) select gp_segment_id, * from bar_randDistr where col1 =3 and gp_segment_id in (0,1);
explain (costs off) select gp_segment_id, * from bar_randDistr where col1 =3 and gp_segment_id <>1;
explain (costs off) select gp_segment_id, * from bar_randDistr where col1 between 1 and 5 and gp_segment_id =0;
explain (costs off) select gp_segment_id, * from bar_randDistr where col1 in (1,5) and gp_segment_id <> 0;
explain (costs off) select gp_segment_id, * from bar_randDistr where col1 in (1,5) and gp_segment_id in (0,1);
-- Case5: Scenarios with special conditions
create function afunc() returns integer as $$ begin return 42; end; $$ language plpgsql;
create function immutable_func() returns integer as $$ begin return 42; end; $$ language plpgsql immutable;
explain (costs off) select * from bar_randDistr where col1 = 1;
explain (costs off) select * from bar_randDistr where gp_segment_id % 2 = 0;
explain (costs off) select * from bar_randDistr where gp_segment_id=immutable_func();
explain (costs off) select * from bar_randDistr where gp_segment_id=afunc();
drop table if exists bar_randDistr;
-- test direct dispatch via gp_segment_id qual
create table t_test_dd_via_segid(id int);
insert into t_test_dd_via_segid select * from generate_series(1, 6);
explain (costs off) select gp_segment_id, id from t_test_dd_via_segid where gp_segment_id=0;
select gp_segment_id, id from t_test_dd_via_segid where gp_segment_id=0;
explain (costs off) select gp_segment_id, id from t_test_dd_via_segid where gp_segment_id=1;
select gp_segment_id, id from t_test_dd_via_segid where gp_segment_id=1;
explain (costs off) select gp_segment_id, id from t_test_dd_via_segid where gp_segment_id=2;
select gp_segment_id, id from t_test_dd_via_segid where gp_segment_id=2;
explain (costs off) select gp_segment_id, id from t_test_dd_via_segid where gp_segment_id=1 or gp_segment_id=2;
select gp_segment_id, id from t_test_dd_via_segid where gp_segment_id=1 or gp_segment_id=2;
explain (costs off) select gp_segment_id, id from t_test_dd_via_segid where gp_segment_id=1 or gp_segment_id=2 or gp_segment_id=3;
select gp_segment_id, id from t_test_dd_via_segid where gp_segment_id=1 or gp_segment_id=2 or gp_segment_id=3;
explain (costs off) select t1.gp_segment_id, t2.gp_segment_id, * from t_test_dd_via_segid t1, t_test_dd_via_segid t2 where t1.gp_segment_id=t2.id;
select t1.gp_segment_id, t2.gp_segment_id, * from t_test_dd_via_segid t1, t_test_dd_via_segid t2 where t1.gp_segment_id=t2.id;
-- flaky tests
-- explain (costs off) select gp_segment_id, count(*) from t_test_dd_via_segid group by gp_segment_id;
-- select gp_segment_id, count(*) from t_test_dd_via_segid group by gp_segment_id;
-- test direct dispatch via gp_segment_id qual with conjunction
create table t_test_dd_via_segid_conj(a int, b int);
insert into t_test_dd_via_segid_conj select i,i from generate_series(1, 10)i;
explain (costs off) select gp_segment_id, * from t_test_dd_via_segid_conj where gp_segment_id=0 and a between 1 and 10;
select gp_segment_id, * from t_test_dd_via_segid_conj where gp_segment_id=0 and a between 1 and 10;
explain (costs off) select gp_segment_id, * from t_test_dd_via_segid_conj where b between 1 and 5 and gp_segment_id=2 and a between 1 and 10;
select gp_segment_id, * from t_test_dd_via_segid_conj where b between 1 and 5 and gp_segment_id=2 and a between 1 and 10;
--test direct dispatch via gp_segment_id with disjunction
explain (costs off) select * from t_test_dd_via_segid_conj where gp_segment_id=1 or (a=3 and gp_segment_id=2);
select * from t_test_dd_via_segid_conj where gp_segment_id=1 or (a=3 and gp_segment_id=2);
--test direct dispatch with constant distribution column and constant/variable gp_segment_id condition
explain (costs off) select gp_segment_id, * from t_test_dd_via_segid_conj where a =3 and b between 1 and 10 and gp_segment_id in (0,1);
select gp_segment_id, * from t_test_dd_via_segid_conj where a =3 and b between 1 and 10 and gp_segment_id in (0,1);
explain (costs off) select gp_segment_id, * from t_test_dd_via_segid_conj where a =3 and b between 1 and 10 and gp_segment_id <>1;
select gp_segment_id, * from t_test_dd_via_segid_conj where a =3 and b between 1 and 10 and gp_segment_id <>1;
explain (costs off) select gp_segment_id, * from t_test_dd_via_segid_conj where a =3 and b between 1 and 100 and gp_segment_id =0;
select gp_segment_id, * from t_test_dd_via_segid_conj where a =3 and b between 1 and 100 and gp_segment_id =0;
explain (costs off) select gp_segment_id, * from t_test_dd_via_segid_conj where a in (1,3) and gp_segment_id <> 0;
select gp_segment_id, * from t_test_dd_via_segid_conj where a in (1,3) and gp_segment_id <> 0;
explain (costs off) select gp_segment_id, * from t_test_dd_via_segid_conj where a in (1,3) and gp_segment_id in (0,1);
select gp_segment_id, * from t_test_dd_via_segid_conj where a in (1,3) and gp_segment_id in (0,1);
--test direct dispatch if distribution column is of varchar type
drop table if exists t1_varchar;
create table t1_varchar(col1_varchar varchar, col2_int int);
insert into t1_varchar values ('a',1);
insert into t1_varchar values ('b',2);
insert into t1_varchar values ('c',3);
insert into t1_varchar values ('d',4);
insert into t1_varchar values ('e',5);
insert into t1_varchar values ('97',6);
explain (costs off) select gp_segment_id, * from t1_varchar where col1_varchar = 'c';
select gp_segment_id, * from t1_varchar where col1_varchar = 'c';
explain (costs off) select gp_segment_id, * from t1_varchar where col1_varchar <>'c';
select gp_segment_id, * from t1_varchar where col1_varchar <>'c';
--test direct dispatch if distribution column is of varchar type and disjunction scenario
explain (costs off) select gp_segment_id, * from t1_varchar where col1_varchar in ('a','b');
select gp_segment_id, * from t1_varchar where col1_varchar in ('a','b');
explain (costs off) select gp_segment_id, * from t1_varchar where col1_varchar = 'a' or col1_varchar = 'b';
select gp_segment_id, * from t1_varchar where col1_varchar = 'a' or col1_varchar = 'b';
--test direct dispatch if distribution column is of varchar type, having disjunction condition
-- or an additional conjunction constraint using another table column or both
explain (costs off) select gp_segment_id, * from t1_varchar where col1_varchar = 'c' and col2_int=3;
select gp_segment_id, * from t1_varchar where col1_varchar = 'c' and col2_int=3;
explain (costs off) select gp_segment_id, * from t1_varchar where col1_varchar = 'a' and col2_int in (1,3);
select gp_segment_id, * from t1_varchar where col1_varchar = 'a' and col2_int in (1,3);
explain (costs off) select gp_segment_id, * from t1_varchar where col1_varchar = 'a' and col2_int not in (2,3);
select gp_segment_id, * from t1_varchar where col1_varchar = 'a' and col2_int not in (2,3);
explain (costs off) select gp_segment_id, * from t1_varchar where col1_varchar in ('a', 'b') and col2_int=2;
select gp_segment_id, * from t1_varchar where col1_varchar in ('a', 'b') and col2_int=2;
explain (costs off) select gp_segment_id, * from t1_varchar where (col1_varchar = 'a' or col1_varchar = 'b') and col2_int=1;
select gp_segment_id, * from t1_varchar where (col1_varchar = 'a' or col1_varchar = 'b') and col2_int=1;
--Test direct dispatch with explicit typecasting
explain (costs off) select gp_segment_id, * from t1_varchar where col1_varchar = 97::VARCHAR;
select gp_segment_id, * from t1_varchar where col1_varchar = 97::VARCHAR;
-- varchar hash and bpchar hash belong to different opfamilies
-- hash distribution of col1_varchar and col1_varchar::bpchar
-- could assign values to different segments. Therefore, the
-- gather motion applies to all 3 segments, and no direct
-- dispatch occurs.
explain (costs off) select gp_segment_id, * from t1_varchar where col1_varchar = 'c'::char;
select gp_segment_id, * from t1_varchar where col1_varchar = 'c'::char;
explain (costs off) select gp_segment_id, * from t1_varchar where col1_varchar = '2'::char;
select gp_segment_id, * from t1_varchar where col1_varchar = '2'::char;
--No direct dispatch case, scenario: cast exists but not binary coercible
drop table if exists t3;
create table t3 (c1 timestamp without time zone);
insert into t3 values ('2015-07-03 00:00:00'::timestamp without time zone);
explain (costs off) select c1 from t3 where c1 = '2015-07-03'::date;
select c1 from t3 where c1 = '2015-07-03'::date;
drop table t3;
drop table t1_varchar;
--check direct dispatch working based on the distribution policy of relation
drop extension if exists citext cascade;
drop table if exists srt_dd;
CREATE EXTENSION citext;
create table srt_dd (name CITEXT);
INSERT INTO srt_dd (name)
VALUES ('abb'),
('ABA'),
('ABC'),
('abd');
-- text hash/btree and citext hash/btree belong to different opfamilies
-- hash distribution of name and name::text could assign values to
-- different segments. Therefore, the gather motion applies to all 3
-- segments, and no direct dispatch occurs.
explain (costs off) select LOWER(name) as aba FROM srt_dd WHERE name = 'ABA'::text;
select LOWER(name) as aba FROM srt_dd WHERE name = 'ABA'::text;
explain (costs off) delete from srt_dd where name='ABA'::text;
delete from srt_dd where name='ABA'::text;
drop extension if exists citext cascade;
drop table if exists srt_dd;
-- test direct dispatch via SQLValueFunction and FuncExpr for single row insertion.
create table t_sql_value_function1 (a int, b date);
create table t_sql_value_function2 (a date);
explain (costs off) insert into t_sql_value_function1 values(1, current_timestamp);
insert into t_sql_value_function1 values(1, current_timestamp);
explain (costs off) insert into t_sql_value_function2 values(current_timestamp);
insert into t_sql_value_function2 values(current_timestamp);
explain (costs off) insert into t_sql_value_function1 values(2, now());
insert into t_sql_value_function1 values(2, now());
explain (costs off) insert into t_sql_value_function2 values(now());
insert into t_sql_value_function2 values(now());
-- Convert policy of root to random when one of its children has a different distribution policy.
-- The only allowed difference between parent and children is for the parent to be hash distributed,
-- and its child part to be randomly distributed.
create table t_hash_partition
(
r_regionkey integer not null,
r_name char(25)
)
partition by range (r_regionkey)
(
partition region1 start (0),
partition region2 start (3),
partition region3 start (5) end (8)
);
set allow_system_table_mods=true;
-- select: root & leaf are all the same hash dist, will direct dispatch
begin;
select * from t_hash_partition where r_regionkey=1;
select * from t_hash_partition_1_prt_region1 where r_regionkey=1;
abort;
-- delete: root & leaf are all the same hash dist, will direct dispatch
begin;
-- orca does not handle direct dispatch for DELETE or UPDATE now
-- also orca does not handle DELETE/UPDATE for partitioned tables now.
explain (costs off) delete from t_hash_partition where r_regionkey=1;
delete from t_hash_partition where r_regionkey=1;
abort;
begin;
-- orca does not handle direct dispatch for DELETE or UPDATE now
delete from t_hash_partition_1_prt_region1 where r_regionkey=1;
abort;
-- update: root & leaf are all the same hash dist, will direct dispatch
begin;
-- orca does not handle direct dispatch for DELETE or UPDATE now
-- also orca does not handle DELETE/UPDATE for partitioned tables now.
explain (costs off) update t_hash_partition set r_name = 'CHINA' where r_regionkey=1;
update t_hash_partition set r_name = 'CHINA' where r_regionkey=1;
abort;
begin;
-- orca does not handle direct dispatch for DELETE or UPDATE now
update t_hash_partition_1_prt_region1 set r_name = 'CHINA' where r_regionkey=1;
abort;
-- insert
begin;
-- only consider target's policy, will direct dispatch
insert into t_hash_partition values(1,'CHINA');
-- leaf is also hash dist, will direct dispatch
insert into t_hash_partition_1_prt_region1 values(1,'CHINA');
abort;
-- can not alter distributed of child partition, we change one child policy to random
update gp_distribution_policy set distkey='',distclass='' where localoid::regclass::text = 't_hash_partition_1_prt_region1';
-- select
begin;
-- root & leaf policy mismatch, will not direct dispatch
select * from t_hash_partition where r_regionkey=1;
-- the leaf is randomly dist now, will not direct dispatch
select * from t_hash_partition_1_prt_region1 where r_regionkey=1;
abort;
-- delete
begin;
-- root & leaf policy mismatch, will not direct dispatch
delete from t_hash_partition where r_regionkey=1;
abort;
begin;
-- this leaf is randomly dist, will not direct dispatch
delete from t_hash_partition_1_prt_region1 where r_regionkey=1;
abort;
-- update
begin;
-- root & leaf policy mismatch, will not direct dispatch
update t_hash_partition set r_name = 'CHINA' where r_regionkey=1;
abort;
begin;
-- this leaf is randomly dist, will not direct dispatch
update t_hash_partition_1_prt_region1 set r_name = 'CHINA' where r_regionkey=1;
abort;
-- insert
begin;
-- only consider target's policy, will direct dispatch
insert into t_hash_partition values(1,'CHINA');
abort;
begin;
-- this leaf is randomly dist, will not direct dispatch
insert into t_hash_partition_1_prt_region1 values(1,'CHINA');
abort;
-- cleanup
set test_print_direct_dispatch_info=off;
set allow_system_table_mods=off;
-- https://github.com/greenplum-db/gpdb/issues/14887
-- If opno of clause does not belong to opfamily of distributed key,
-- do not use direct dispatch to resolve wrong result
create table t_14887(a varchar);
insert into t_14887 values('a ');
explain select * from t_14887 where a = 'a'::bpchar;
select * from t_14887 where a = 'a'::bpchar;
-- texteq does not belong to the hash opfamily of the table's citext distkey.
-- But from the implementation can deduce: texteq ==> citext_eq, and we can
-- do the direct dispatch.
-- But we do not have the kind of implication rule in Postgres: texteq ==> citext_eq.
-- Also partition table with citext as hash key and condition with text type
-- does not do partition prune.
CREATE EXTENSION if not exists citext;
drop table t_14887;
create table t_14887(a citext);
insert into t_14887 values('A'),('a');
explain select * from t_14887 where a = 'a'::text;
select * from t_14887 where a = 'a'::text;
drop table t_14887;
create table t_14887 (a citext) partition by hash (a);
create table t0_14887 partition of t_14887 for values with (modulus 3,remainder 0);
create table t1_14887 partition of t_14887 for values with (modulus 3,remainder 1);
create table t2_14887 partition of t_14887 for values with (modulus 3,remainder 2);
explain select * from t_14887 where a = 'a'::text;
begin;
drop table if exists direct_test;
drop table if exists direct_test_two_column;
drop table if exists direct_test_bitmap;
drop table if exists direct_test_partition;
drop table if exists direct_test_range_partition;
drop table if exists direct_dispatch_foo;
drop table if exists direct_dispatch_bar;
drop table if exists MPP_22019_a;
drop table if exists MPP_22019_b;
drop table if exists t_sql_value_function1;
drop table if exists t_sql_value_function2;
drop table if exists t_hash_partition;
drop table if exists t_14887;
drop extension if exists citext cascade;
commit;