| -- =================================================================== |
| -- Cloudberry-specific features for postgres_fdw |
| -- =================================================================== |
| |
| -- =================================================================== |
| -- Create source tables and populate with data |
| -- =================================================================== |
| CREATE SCHEMA postgres_fdw_gp; |
| set search_path=postgres_fdw_gp; |
| CREATE EXTENSION IF NOT EXISTS postgres_fdw; |
| |
| DO $d$ |
| BEGIN |
| EXECUTE $$CREATE SERVER loopback FOREIGN DATA WRAPPER postgres_fdw |
| OPTIONS (dbname '$$||current_database()||$$', |
| port '$$||current_setting('port')||$$' |
| )$$; |
| END; |
| $d$; |
| |
| CREATE USER MAPPING IF NOT EXISTS FOR CURRENT_USER SERVER loopback; |
| |
| CREATE EXTENSION postgres_fdw; |
| |
| CREATE SERVER testserver1 FOREIGN DATA WRAPPER postgres_fdw; |
| DO $d$ |
| BEGIN |
| EXECUTE $$CREATE SERVER loopback FOREIGN DATA WRAPPER postgres_fdw |
| OPTIONS (dbname '$$||current_database()||$$', |
| port '$$||current_setting('port')||$$' |
| )$$; |
| EXECUTE $$CREATE SERVER loopback2 FOREIGN DATA WRAPPER postgres_fdw |
| OPTIONS (dbname '$$||current_database()||$$', |
| port '$$||current_setting('port')||$$' |
| )$$; |
| EXECUTE $$CREATE SERVER loopback3 FOREIGN DATA WRAPPER postgres_fdw |
| OPTIONS (dbname '$$||current_database()||$$', |
| port '$$||current_setting('port')||$$' |
| )$$; |
| END; |
| $d$; |
| |
| CREATE USER MAPPING FOR public SERVER testserver1 |
| OPTIONS (user 'value', password 'value'); |
| CREATE USER MAPPING FOR CURRENT_USER SERVER loopback; |
| CREATE USER MAPPING FOR CURRENT_USER SERVER loopback2; |
| CREATE USER MAPPING FOR public SERVER loopback3; |
| |
| CREATE SCHEMA "S 1"; |
| |
| CREATE TABLE table_dist_rand |
| ( |
| f1 int, |
| f2 text, |
| f3 text |
| ) DISTRIBUTED RANDOMLY; |
| |
| CREATE TABLE table_dist_repl |
| ( |
| f1 int, |
| f2 text, |
| f3 text |
| ) DISTRIBUTED REPLICATED; |
| |
| CREATE TABLE table_dist_int |
| ( |
| f1 int, |
| f2 text, |
| f3 text |
| ) DISTRIBUTED BY (f1); |
| |
| CREATE TABLE table_dist_text |
| ( |
| f1 int, |
| f2 text, |
| f3 text |
| ) DISTRIBUTED BY (f2); |
| |
| CREATE TABLE table_dist_int_text |
| ( |
| f1 int, |
| f2 text, |
| f3 text |
| ) DISTRIBUTED BY (f1, f2); |
| |
| INSERT INTO table_dist_rand |
| VALUES (1, 'a', 'aa'), |
| (2, 'b', 'bb'), |
| (3, 'c', 'cc'), |
| (4, 'd', 'dd'), |
| (5, 'e', 'ee'), |
| (6, 'f', 'ff'), |
| (7, 'g', 'gg'), |
| (8, 'h', 'hh'), |
| (9, 'i', 'ii'), |
| (10, 'j', 'jj'), |
| (11, 'k', 'kk'), |
| (12, 'l', 'll'); |
| |
| INSERT INTO table_dist_repl SELECT * FROM table_dist_rand; |
| INSERT INTO table_dist_int SELECT * FROM table_dist_rand; |
| INSERT INTO table_dist_text SELECT * FROM table_dist_rand; |
| INSERT INTO table_dist_int_text SELECT * FROM table_dist_rand; |
| |
| -- =================================================================== |
| -- create target table |
| -- =================================================================== |
| |
| CREATE TABLE postgres_fdw_gp."GP 1" ( |
| f1 int, |
| f2 text, |
| f3 text |
| ); |
| |
| -- =================================================================== |
| -- create foreign tables |
| -- =================================================================== |
| |
| CREATE FOREIGN TABLE gp_ft1 ( |
| f1 int, |
| f2 text, |
| f3 text |
| ) SERVER loopback OPTIONS (schema_name 'postgres_fdw_gp', table_name 'GP 1', mpp_execute 'all segments'); |
| |
| -- =================================================================== |
| -- validate parallel writes (mpp_execute set to all segments) |
| -- =================================================================== |
| |
| EXPLAIN (VERBOSE, COSTS FALSE) SELECT * FROM gp_ft1; |
| EXPLAIN (COSTS FALSE) INSERT INTO gp_ft1 SELECT * FROM table_dist_rand; |
| INSERT INTO gp_ft1 SELECT * FROM table_dist_rand; |
| SELECT * FROM postgres_fdw_gp."GP 1" ORDER BY f1; |
| TRUNCATE TABLE postgres_fdw_gp."GP 1"; |
| |
| \c |
| set search_path=postgres_fdw_gp; |
| alter server loopback options(add num_segments '2'); |
| EXPLAIN (VERBOSE, COSTS FALSE) SELECT * FROM gp_ft1; |
| EXPLAIN (COSTS FALSE) INSERT INTO gp_ft1 SELECT * FROM table_dist_rand; |
| INSERT INTO gp_ft1 SELECT * FROM table_dist_rand; |
| SELECT * FROM postgres_fdw_gp."GP 1" ORDER BY f1; |
| TRUNCATE TABLE postgres_fdw_gp."GP 1"; |
| alter server loopback options(drop num_segments); |
| \c |
| set search_path=postgres_fdw_gp; |
| |
| EXPLAIN (COSTS FALSE) INSERT INTO gp_ft1 SELECT * FROM table_dist_repl; |
| INSERT INTO gp_ft1 SELECT * FROM table_dist_repl; |
| SELECT * FROM postgres_fdw_gp."GP 1" ORDER BY f1; |
| TRUNCATE TABLE postgres_fdw_gp."GP 1"; |
| |
| EXPLAIN (COSTS FALSE) INSERT INTO gp_ft1 SELECT * FROM table_dist_int; |
| INSERT INTO gp_ft1 SELECT * FROM table_dist_int; |
| SELECT * FROM postgres_fdw_gp."GP 1" ORDER BY f1; |
| TRUNCATE TABLE postgres_fdw_gp."GP 1"; |
| |
| EXPLAIN (COSTS FALSE) INSERT INTO gp_ft1 SELECT * FROM table_dist_text; |
| INSERT INTO gp_ft1 SELECT * FROM table_dist_text; |
| SELECT * FROM postgres_fdw_gp."GP 1" ORDER BY f1; |
| TRUNCATE TABLE postgres_fdw_gp."GP 1"; |
| |
| EXPLAIN (COSTS FALSE) INSERT INTO gp_ft1 SELECT * FROM table_dist_int_text; |
| INSERT INTO gp_ft1 SELECT * FROM table_dist_int_text; |
| SELECT * FROM postgres_fdw_gp."GP 1" ORDER BY f1; |
| TRUNCATE TABLE postgres_fdw_gp."GP 1"; |
| |
| EXPLAIN (COSTS FALSE) INSERT INTO gp_ft1 |
| SELECT id, |
| 'AAA' || to_char(id, 'FM000'), |
| 'BBB' || to_char(id, 'FM000') |
| FROM generate_series(1, 100) id; |
| INSERT INTO gp_ft1 |
| SELECT id, |
| 'AAA' || to_char(id, 'FM000'), |
| 'BBB' || to_char(id, 'FM000') |
| FROM generate_series(1, 100) id; |
| SELECT * FROM postgres_fdw_gp."GP 1" ORDER BY f1; |
| TRUNCATE TABLE postgres_fdw_gp."GP 1"; |
| |
| -- =================================================================== |
| -- validate writes on any segment (mpp_execute set to any) |
| -- =================================================================== |
| |
| ALTER FOREIGN TABLE gp_ft1 OPTIONS ( SET mpp_execute 'any' ); |
| |
| EXPLAIN (COSTS FALSE) INSERT INTO gp_ft1 SELECT * FROM table_dist_rand; |
| INSERT INTO gp_ft1 SELECT * FROM table_dist_rand; |
| SELECT * FROM postgres_fdw_gp."GP 1" ORDER BY f1; |
| TRUNCATE TABLE postgres_fdw_gp."GP 1"; |
| |
| EXPLAIN (COSTS FALSE) INSERT INTO gp_ft1 SELECT * FROM table_dist_repl; |
| INSERT INTO gp_ft1 SELECT * FROM table_dist_repl; |
| SELECT * FROM postgres_fdw_gp."GP 1" ORDER BY f1; |
| TRUNCATE TABLE postgres_fdw_gp."GP 1"; |
| |
| EXPLAIN (COSTS FALSE) INSERT INTO gp_ft1 SELECT * FROM table_dist_int; |
| INSERT INTO gp_ft1 SELECT * FROM table_dist_int; |
| SELECT * FROM postgres_fdw_gp."GP 1" ORDER BY f1; |
| TRUNCATE TABLE postgres_fdw_gp."GP 1"; |
| |
| EXPLAIN (COSTS FALSE) INSERT INTO gp_ft1 SELECT * FROM table_dist_text; |
| INSERT INTO gp_ft1 SELECT * FROM table_dist_text; |
| SELECT * FROM postgres_fdw_gp."GP 1" ORDER BY f1; |
| TRUNCATE TABLE postgres_fdw_gp."GP 1"; |
| |
| EXPLAIN (COSTS FALSE) INSERT INTO gp_ft1 SELECT * FROM table_dist_int_text; |
| INSERT INTO gp_ft1 SELECT * FROM table_dist_int_text; |
| SELECT * FROM postgres_fdw_gp."GP 1" ORDER BY f1; |
| TRUNCATE TABLE postgres_fdw_gp."GP 1"; |
| |
| EXPLAIN (COSTS FALSE) INSERT INTO gp_ft1 |
| SELECT id, |
| 'AAA' || to_char(id, 'FM000'), |
| 'BBB' || to_char(id, 'FM000') |
| FROM generate_series(1, 100) id; |
| INSERT INTO gp_ft1 |
| SELECT id, |
| 'AAA' || to_char(id, 'FM000'), |
| 'BBB' || to_char(id, 'FM000') |
| FROM generate_series(1, 100) id; |
| SELECT * FROM postgres_fdw_gp."GP 1" ORDER BY f1; |
| TRUNCATE TABLE postgres_fdw_gp."GP 1"; |
| |
| -- =================================================================== |
| -- validate writes on master (mpp_execute set to master) |
| -- =================================================================== |
| |
| ALTER FOREIGN TABLE gp_ft1 OPTIONS ( SET mpp_execute 'master' ); |
| |
| EXPLAIN (COSTS FALSE) INSERT INTO gp_ft1 SELECT * FROM table_dist_rand; |
| INSERT INTO gp_ft1 SELECT * FROM table_dist_rand; |
| SELECT * FROM postgres_fdw_gp."GP 1" ORDER BY f1; |
| TRUNCATE TABLE postgres_fdw_gp."GP 1"; |
| |
| EXPLAIN (COSTS FALSE) INSERT INTO gp_ft1 SELECT * FROM table_dist_repl; |
| INSERT INTO gp_ft1 SELECT * FROM table_dist_repl; |
| SELECT * FROM postgres_fdw_gp."GP 1" ORDER BY f1; |
| TRUNCATE TABLE postgres_fdw_gp."GP 1"; |
| |
| EXPLAIN (COSTS FALSE) INSERT INTO gp_ft1 SELECT * FROM table_dist_int; |
| INSERT INTO gp_ft1 SELECT * FROM table_dist_int; |
| SELECT * FROM postgres_fdw_gp."GP 1" ORDER BY f1; |
| TRUNCATE TABLE postgres_fdw_gp."GP 1"; |
| |
| EXPLAIN (COSTS FALSE) INSERT INTO gp_ft1 SELECT * FROM table_dist_text; |
| INSERT INTO gp_ft1 SELECT * FROM table_dist_text; |
| SELECT * FROM postgres_fdw_gp."GP 1" ORDER BY f1; |
| TRUNCATE TABLE postgres_fdw_gp."GP 1"; |
| |
| EXPLAIN (COSTS FALSE) INSERT INTO gp_ft1 SELECT * FROM table_dist_int_text; |
| INSERT INTO gp_ft1 SELECT * FROM table_dist_int_text; |
| SELECT * FROM postgres_fdw_gp."GP 1" ORDER BY f1; |
| TRUNCATE TABLE postgres_fdw_gp."GP 1"; |
| |
| EXPLAIN (COSTS FALSE) INSERT INTO gp_ft1 |
| SELECT id, |
| 'AAA' || to_char(id, 'FM000'), |
| 'BBB' || to_char(id, 'FM000') |
| FROM generate_series(1, 100) id; |
| INSERT INTO gp_ft1 |
| SELECT id, |
| 'AAA' || to_char(id, 'FM000'), |
| 'BBB' || to_char(id, 'FM000') |
| FROM generate_series(1, 100) id; |
| SELECT * FROM postgres_fdw_gp."GP 1" ORDER BY f1; |
| TRUNCATE TABLE postgres_fdw_gp."GP 1"; |
| |
| -- Validate queries on different execution locations |
| create table t1(a int, b int); |
| create table t2(a int, b int); |
| create table t3(a int, b int); |
| |
| CREATE FOREIGN TABLE gp_all ( |
| a int, |
| b int |
| ) SERVER loopback OPTIONS (schema_name 'postgres_fdw_gp', table_name 't1', mpp_execute 'all segments'); |
| |
| CREATE FOREIGN TABLE gp_any ( |
| a int, |
| b int |
| ) SERVER loopback OPTIONS (schema_name 'postgres_fdw_gp', table_name 't2', mpp_execute 'any'); |
| |
| CREATE FOREIGN TABLE gp_coord ( |
| a int, |
| b int |
| ) SERVER loopback OPTIONS (schema_name 'postgres_fdw_gp', table_name 't3', mpp_execute 'coordinator'); |
| |
| create table part_mixed (a int, b int) partition by range (b); |
| alter table part_mixed attach partition gp_all for values from (0) to (5); |
| alter table part_mixed attach partition gp_any for values from (5) to (10); |
| alter table part_mixed attach partition gp_coord for values from (10) to (15); |
| insert into part_mixed select i,i from generate_series(0,14)i; |
| analyze part_mixed; |
| |
| explain select * from gp_all; |
| select * from gp_all; |
| |
| explain select * from gp_any; |
| select * from gp_any; |
| |
| explain select * from gp_coord; |
| select * from gp_coord; |
| |
| -- validate partition with different execution locations |
| explain select * from part_mixed; |
| select * from part_mixed; |
| |
| -- validate joins on different execution locations |
| create table non_part (a int, b int); |
| insert into non_part select i, i from generate_series(8,12)i; |
| analyze non_part; |
| |
| explain select * from part_mixed join non_part on part_mixed.a=non_part.a; |
| select * from part_mixed join non_part on part_mixed.a=non_part.a; |
| |
| explain select * from part_mixed left join non_part on part_mixed.a=non_part.a; |
| select * from part_mixed left join non_part on part_mixed.a=non_part.a; |
| |
| explain select * from part_mixed right join non_part on part_mixed.a=non_part.a; |
| select * from part_mixed right join non_part on part_mixed.a=non_part.a; |
| |
| -- validate join is on segments for distributed table |
| explain select * from gp_any, table_dist_int where gp_any.a=table_dist_int.f1; |
| select * from gp_any, table_dist_int where gp_any.a=table_dist_int.f1; |
| |
| -- validate join is on segments for replicated table |
| explain select * from gp_any, table_dist_repl where gp_any.a=table_dist_repl.f1; |
| select * from gp_any, table_dist_repl where gp_any.a=table_dist_repl.f1; |
| |
| create table part_mixed_dpe(a int, b int) partition by range(b); |
| alter table part_mixed detach partition gp_any; |
| alter table part_mixed_dpe attach partition gp_any for values from (5) to (10); |
| insert into part_mixed_dpe select 6,6 from generate_series(1,10); |
| analyze part_mixed_dpe; |
| explain select * from part_mixed_dpe, non_part where part_mixed_dpe.b=non_part.b; |
| select * from part_mixed_dpe, non_part where part_mixed_dpe.b=non_part.b; |
| |
| -- compare difference plans among when mpp_execute set to 'all segments', 'coordinator' and 'any' |
| explain (costs false) update t1 set b = b + 1 where b in (select a from gp_all where gp_all.a > 10); |
| explain (costs false) update t1 set b = b + 1 where b in (select a from gp_any where gp_any.a > 10); |
| explain (costs false) update t1 set b = b + 1 where b in (select a from gp_coord where gp_coord.a > 10); |
| |
| --- |
| --- Test for #16376 of multi-level partition table with foreign table |
| --- |
| CREATE TABLE sub_part ( |
| a int, |
| b int, |
| c int) |
| DISTRIBUTED BY (a) |
| partition by range(b) subpartition by list(c) |
| SUBPARTITION TEMPLATE |
| ( |
| SUBPARTITION one values (1), |
| SUBPARTITION two values (2) |
| ) |
| ( |
| START (0) INCLUSIVE END (5) EXCLUSIVE EVERY (1) |
| ); |
| |
| -- Create foreign tables |
| CREATE FOREIGN TABLE sub_part_1_prt_1_2_prt_one_foreign ( |
| a int, |
| b int, |
| c int) |
| SERVER loopback; |
| |
| CREATE FOREIGN TABLE sub_part_1_prt_1_2_prt_two_foreign ( |
| a int, |
| b int, |
| c int) |
| SERVER loopback; |
| |
| -- change a sub partition's all leaf table to foreign table |
| ALTER TABLE sub_part_1_prt_1 EXCHANGE PARTITION for(1) WITH TABLE sub_part_1_prt_1_2_prt_one_foreign; |
| ALTER TABLE sub_part_1_prt_1 EXCHANGE PARTITION for(2) WITH TABLE sub_part_1_prt_1_2_prt_two_foreign; |
| |
| -- explain with ORCA should fall back to planner, rather than raise ERROR |
| explain select * from sub_part; |
| |
| --- Clean up |
| DROP TABLE sub_part; |
| DROP TABLE sub_part_1_prt_1_2_prt_one_foreign; |
| DROP TABLE sub_part_1_prt_1_2_prt_two_foreign; |
| |
| -- GPDB #16219: validate scram-sha-256 in postgres_fdw |
| alter system set password_encryption = 'scram-sha-256'; |
| -- add created user to pg_hba.conf |
| \! echo "host all u16219 0.0.0.0/0 scram-sha-256" >> $COORDINATOR_DATA_DIRECTORY/pg_hba.conf |
| \! echo "host all u16219 ::1/128 scram-sha-256" >> $COORDINATOR_DATA_DIRECTORY/pg_hba.conf |
| \! echo "local all u16219 scram-sha-256" >> $COORDINATOR_DATA_DIRECTORY/pg_hba.conf |
| select pg_reload_conf(); |
| \c postgres |
| create user u16219 password '123456'; |
| |
| create database database_16219; |
| \c database_16219 |
| create extension postgres_fdw; |
| grant usage on FOREIGN DATA WRAPPER postgres_fdw to public; |
| |
| set role u16219; |
| create table t1 (a int, b int); |
| insert into t1 values(generate_series(1,10),generate_series(11,20)); |
| |
| DO $d$ |
| BEGIN |
| EXECUTE $$CREATE SERVER database_16219 FOREIGN DATA WRAPPER postgres_fdw |
| OPTIONS (dbname '$$||current_database()||$$', |
| port '$$||current_setting('port')||$$', |
| host 'localhost' |
| )$$; |
| END; |
| $d$; |
| |
| CREATE USER MAPPING FOR CURRENT_USER SERVER database_16219 |
| OPTIONS (user 'u16219', password '123456'); |
| |
| CREATE FOREIGN TABLE f_t1(a int, b int) |
| server database_16219 options(schema_name 'public', table_name 't1'); |
| |
| select count(*) from f_t1; |
| DO $d$ |
| BEGIN |
| EXECUTE $$ALTER SERVER database_16219 |
| OPTIONS (SET port '$$||current_setting('port')||$$')$$; |
| END; |
| $d$; |
| select count(*) from f_t1; |
| \c postgres |
| drop database database_16219; |
| drop user u16219; |
| alter system reset password_encryption; |
| select pg_reload_conf(); |