blob: cc9bd2fe2fe89bbe647adce7b918d870cb6ff245 [file] [log] [blame]
-- This file is used to test the feature that there are multiple remote postgres servers.
-- ===================================================================
-- create FDW objects
-- ===================================================================
SET timezone = 'PST8PDT';
-- If gp_enable_minmax_optimization is on, it won't generate aggregate functions pushdown plan.
SET gp_enable_minmax_optimization = off;
-- Clean
-- start_ignore
DROP EXTENSION IF EXISTS postgres_fdw CASCADE;
-- end_ignore
CREATE EXTENSION postgres_fdw;
CREATE SERVER pgserver FOREIGN DATA WRAPPER postgres_fdw
OPTIONS (host 'dummy', port '0',
dbname 'contrib_regression', multi_hosts 'localhost localhost',
multi_ports '5432 5555', num_segments '2', mpp_execute 'all segments');
CREATE USER MAPPING FOR CURRENT_USER SERVER pgserver;
-- ===================================================================
-- create objects used through FDW pgserver server
-- ===================================================================
-- remote postgres server 1 -- listening port 5432
\! env PGOPTIONS='' psql -p 5432 contrib_regression -f sql/postgres_sql/mpp_gp2pg_postgres_init_1.sql
-- remote postgres server 2 -- listening port 5555
\! env PGOPTIONS='' psql -p 5555 contrib_regression -f sql/postgres_sql/mpp_gp2pg_postgres_init_2.sql
-- ===================================================================
-- create foreign tables
-- ===================================================================
CREATE FOREIGN TABLE mpp_ft1 (
c1 int,
c2 int
) SERVER pgserver OPTIONS (schema_name 'MPP_S 1', table_name 'T 1');
CREATE FOREIGN TABLE mpp_ft2 (
c1 int,
c2 int,
c3 smallint,
c4 bigint,
c5 real,
c6 double precision,
c7 numeric
) SERVER pgserver OPTIONS (schema_name 'MPP_S 1', table_name 'T 2');
-- ===================================================================
-- tests for validator
-- ===================================================================
-- Error when the length of option multi_hosts and multi_ports is NOT same.
CREATE SERVER testserver FOREIGN DATA WRAPPER postgres_fdw
OPTIONS (dbname 'contrib_regression', multi_hosts 'localhost localhost',
multi_ports '5432', num_segments '2', mpp_execute 'all segments');
-- Error when specifying option multi_hosts and multi_ports but option mpp_execute is NOT 'all segments'.
CREATE FOREIGN TABLE mpp_test (
c1 int,
c2 int
) SERVER pgserver OPTIONS (schema_name 'MPP_S 1', table_name 'T 1', mpp_execute 'coordinator');
SELECT * FROM mpp_test;
ALTER FOREIGN TABLE mpp_test OPTIONS (drop mpp_execute);
-- Error when the value of option num_segments is NOT same as the length of option multi_hosts and multi_ports.
ALTER SERVER pgserver OPTIONS (set num_segments '1');
SELECT * FROM mpp_test;
ALTER SERVER pgserver OPTIONS (set num_segments '2');
-- ===================================================================
-- Simple queries
-- ===================================================================
EXPLAIN VERBOSE SELECT * FROM mpp_ft1 ORDER BY c1;
SELECT * FROM mpp_ft1 ORDER BY c1;
ANALYZE mpp_ft1;
ALTER FOREIGN TABLE mpp_ft1 OPTIONS (add use_remote_estimate 'true');
EXPLAIN VERBOSE SELECT * FROM mpp_ft1 ORDER BY c1;
SELECT * FROM mpp_ft1 ORDER BY c1;
ALTER FOREIGN TABLE mpp_ft1 OPTIONS (drop use_remote_estimate);
-- ===================================================================
-- When there are multiple remote servers, we don't support IMPORT FOREIGN SCHEMA
-- ===================================================================
CREATE SCHEMA mpp_import_dest;
IMPORT FOREIGN SCHEMA import_source FROM SERVER pgserver INTO mpp_import_dest;
-- ===================================================================
-- When there are multiple remote servers, we don't support INSERT/UPDATE/DELETE
-- ===================================================================
INSERT INTO mpp_ft1 VALUES (1, 1);
UPDATE mpp_ft1 SET c1 = c1 + 1;
DELETE FROM mpp_ft1;
-- ===================================================================
-- Aggregate and grouping queries
-- ===================================================================
-- Simple aggregates with different data types
EXPLAIN (VERBOSE, COSTS OFF)
SELECT count(c1), count(c3), count(c4), count(c5), count(c6), count(c7) FROM mpp_ft2;
SELECT count(c1), count(c3), count(c4), count(c5), count(c6), count(c7) FROM mpp_ft2;
EXPLAIN (VERBOSE, COSTS OFF)
SELECT sum(c1), sum(c3), sum(c4), sum(c5), sum(c6), sum(c7) FROM mpp_ft2;
SELECT sum(c1), sum(c3), sum(c4), sum(c5), sum(c6), sum(c7) FROM mpp_ft2;
EXPLAIN (VERBOSE, COSTS OFF)
SELECT avg(c1), avg(c3), avg(c4), avg(c5), avg(c6), avg(c7) FROM mpp_ft2;
SELECT avg(c1), avg(c3), avg(c4), avg(c5), avg(c6), avg(c7) FROM mpp_ft2;
EXPLAIN (VERBOSE, COSTS OFF)
SELECT min(c1), min(c3), min(c4), min(c5), min(c6), min(c7) FROM mpp_ft2;
SELECT min(c1), min(c3), min(c4), min(c5), min(c6), min(c7) FROM mpp_ft2;
EXPLAIN (VERBOSE, COSTS OFF)
SELECT max(c1), max(c3), max(c4), max(c5), max(c6), max(c7) FROM mpp_ft2;
SELECT max(c1), max(c3), max(c4), max(c5), max(c6), max(c7) FROM mpp_ft2;
-- Simple Aggregates with GROUP BY clause
EXPLAIN (VERBOSE, COSTS OFF)
SELECT count(c1), sum(c3), avg(c4), min(c5), max(c6), count(c1) * (random() <= 1)::int as count2 FROM mpp_ft2 GROUP BY c2 ORDER BY c2;
SELECT count(c1), sum(c3), avg(c4), min(c5), max(c6), count(c1) * (random() <= 1)::int as count2 FROM mpp_ft2 GROUP BY c2 ORDER BY c2;
-- Aggregate is not pushed down as aggregation contains random()
EXPLAIN (VERBOSE, COSTS OFF)
SELECT sum(c1 * (random() <= 1)::int) as sum, avg(c1) FROM mpp_ft2;
SELECT sum(c1 * (random() <= 1)::int) as sum, avg(c1) FROM mpp_ft2;
-- GROUP BY clause having expressions
/* FIXME: Aggregates are not pushed down.
Because for Remote SQL of partial agg, non-grouping columns
might neither appear in the GROUP BY clause nor be used in
an aggregate function.
This is unsafe to make foreign grouping.
*/
EXPLAIN (VERBOSE, COSTS OFF)
SELECT c2/2, sum(c2) * (c2/2) FROM mpp_ft2 GROUP BY c2/2 ORDER BY c2/2;
SELECT c2/2, sum(c2) * (c2/2) FROM mpp_ft2 GROUP BY c2/2 ORDER BY c2/2;
-- Aggregates in subquery are pushed down.
EXPLAIN (VERBOSE, COSTS OFF)
SELECT count(x.a), sum(x.a) FROM (SELECT c2 a, sum(c1) b FROM mpp_ft2 GROUP BY c2, sqrt(c1) ORDER BY 1, 2) x;
SELECT count(x.a), sum(x.a) FROM (SELECT c2 a, sum(c1) b FROM mpp_ft2 GROUP BY c2, sqrt(c1) ORDER BY 1, 2) x;
-- Aggregate is still pushed down by taking unshippable expression out
EXPLAIN (VERBOSE, COSTS OFF)
SELECT c2 * (random() <= 1)::int as sum1, sum(c1) * c2 as sum2 FROM mpp_ft2 GROUP BY c2 ORDER BY 1, 2;
SELECT c2 * (random() <= 1)::int as sum1, sum(c1) * c2 as sum2 FROM mpp_ft2 GROUP BY c2 ORDER BY 1, 2;
-- Aggregate with unshippable GROUP BY clause are not pushed
EXPLAIN (VERBOSE, COSTS OFF)
SELECT c2 * (random() <= 1)::int as c2 FROM mpp_ft2 GROUP BY c2 * (random() <= 1)::int ORDER BY 1;
SELECT c2 * (random() <= 1)::int as c2 FROM mpp_ft2 GROUP BY c2 * (random() <= 1)::int ORDER BY 1;
-- GROUP BY clause in various forms, cardinal, alias and constant expression
EXPLAIN (VERBOSE, COSTS OFF)
SELECT count(c2) w, c2 x, 5 y, 7.0 z FROM mpp_ft2 GROUP BY 2, y, 9.0::int ORDER BY 2;
SELECT count(c2) w, c2 x, 5 y, 7.0 z FROM mpp_ft2 GROUP BY 2, y, 9.0::int ORDER BY 2;
-- GROUP BY clause referring to same column multiple times
-- Also, ORDER BY contains an aggregate function
EXPLAIN (VERBOSE, COSTS OFF)
SELECT c2, c2 FROM mpp_ft2 WHERE c2 > 6 GROUP BY 1, 2 ORDER BY sum(c1);
SELECT c2, c2 FROM mpp_ft2 WHERE c2 > 6 GROUP BY 1, 2 ORDER BY sum(c1);
-- Testing HAVING clause
-- It's unsafe for partial agg to push down HAVING clause.
EXPLAIN (VERBOSE, COSTS OFF)
SELECT c2, sum(c1) FROM mpp_ft2 GROUP BY c2 HAVING avg(c1) < 500 AND sum(c1) < 49800 ORDER BY c2;
SELECT c2, sum(c1) FROM mpp_ft2 GROUP BY c2 HAVING avg(c1) < 500 AND sum(c1) < 49800 ORDER BY c2;
-- Remote aggregate in combination with a local Param (for the output
-- of an initplan) can be trouble, per bug #15781
EXPLAIN (VERBOSE, COSTS OFF)
SELECT exists(SELECT 1 FROM pg_aggregate), sum(c1) FROM mpp_ft2;
SELECT exists(SELECT 1 FROM pg_aggregate), sum(c1) FROM mpp_ft2;
EXPLAIN (VERBOSE, COSTS OFF)
SELECT exists(SELECT 1 FROM pg_aggregate), sum(c1) FROM mpp_ft2 group by 1;
SELECT exists(SELECT 1 FROM pg_aggregate), sum(c1) FROM mpp_ft2 group by 1;
-- Testing ORDER BY, DISTINCT, FILTER within aggregates
-- ORDER BY within aggregate, same column used to order
-- TODO: Now we don't support array_agg mpp pushdown.
EXPLAIN (VERBOSE, COSTS OFF)
SELECT array_agg(c1 ORDER BY c1) FROM mpp_ft2 WHERE c1 < 100 GROUP BY c2 ORDER BY 1;
SELECT array_agg(c1 ORDER BY c1) FROM mpp_ft2 WHERE c1 < 100 GROUP BY c2 ORDER BY 1;
-- FILTER within aggregate
EXPLAIN (VERBOSE, COSTS OFF)
SELECT sum(c1) FILTER (WHERE c1 < 100 AND c2 > 5) FROM mpp_ft2 GROUP BY c2 ORDER BY 1 nulls last;
SELECT sum(c1) FILTER (WHERE c1 < 100 AND c2 > 5) FROM mpp_ft2 GROUP BY c2 ORDER BY 1 nulls last;
-- DISTINCT, ORDER BY and FILTER within aggregate
-- It's unsafe to push down DISTINCT within aggregates when there are multiple remote servers.
EXPLAIN (VERBOSE, COSTS OFF)
SELECT sum(c1%3), sum(DISTINCT c1%3 ORDER BY c1%3) FILTER (WHERE c1%3 < 2), c2 FROM mpp_ft2 WHERE c2 = 6 GROUP BY c2;
SELECT sum(c1%3), sum(DISTINCT c1%3 ORDER BY c1%3) FILTER (WHERE c1%3 < 2), c2 FROM mpp_ft2 WHERE c2 = 6 GROUP BY c2;
-- Aggregate not pushed down as FILTER condition is not pushable
EXPLAIN (VERBOSE, COSTS OFF)
SELECT sum(c1) FILTER (WHERE (c1 / c1) * random() <= 1) FROM mpp_ft2 GROUP BY c2 ORDER BY 1;
SELECT sum(c1) FILTER (WHERE (c1 / c1) * random() <= 1) FROM mpp_ft2 GROUP BY c2 ORDER BY 1;
-- Set use_remote_estimate to true
ALTER FOREIGN TABLE mpp_ft2 OPTIONS(add use_remote_estimate 'true');
EXPLAIN (VERBOSE, COSTS OFF)
SELECT min(c5) FROM mpp_ft2;
SELECT min(c5) FROM mpp_ft2;
EXPLAIN (VERBOSE, COSTS OFF)
SELECT count(c1), max(c6) FROM mpp_ft2 GROUP BY c2;
SELECT count(c1), max(c6) FROM mpp_ft2 GROUP BY c2;
EXPLAIN (VERBOSE, COSTS OFF)
SELECT count(c1), sum(c3), avg(c4), min(c5), max(c6), count(c1) * (random() <= 1)::int as count2 FROM mpp_ft2 GROUP BY c2 ORDER BY c2;
SELECT count(c1), sum(c3), avg(c4), min(c5), max(c6), count(c1) * (random() <= 1)::int as count2 FROM mpp_ft2 GROUP BY c2 ORDER BY c2;
ALTER FOREIGN TABLE mpp_ft2 OPTIONS(set use_remote_estimate 'false');
-- ===================================================================
-- Queries with LIMIT/OFFSET clauses
-- ===================================================================
-- Simple query with LIMIT clause is pushed down.
EXPLAIN VERBOSE
SELECT c1, c2 FROM mpp_ft2 order by c1 limit 3;
SELECT c1, c2 FROM mpp_ft2 order by c1 limit 3;
-- Simple query with OFFSET and LIMIT clause together is pushed down.
EXPLAIN VERBOSE
SELECT c1, c2 FROM mpp_ft2 order by c1 offset 2 limit 3;
SELECT c1, c2 FROM mpp_ft2 order by c1 offset 2 limit 3;
-- Simple query with only OFFSET clause is NOT pushed down.
EXPLAIN VERBOSE
SELECT c1, c2 FROM mpp_ft2 order by c1 offset 998;
SELECT c1, c2 FROM mpp_ft2 order by c1 offset 998;
-- test LIMIT 0, OFFSET null/0
ALTER FOREIGN TABLE mpp_ft2 OPTIONS(set use_remote_estimate 'true');
EXPLAIN (VERBOSE, COSTS OFF)
SELECT c1, c2 FROM mpp_ft2 order by c1 limit null offset 998;
EXPLAIN (VERBOSE, COSTS OFF)
SELECT c1, c2 FROM mpp_ft2 order by c1 limit all offset 998;
EXPLAIN (VERBOSE, COSTS OFF)
SELECT c1, c2 FROM mpp_ft2 order by c1 limit 0 offset 998;
EXPLAIN (VERBOSE, COSTS OFF)
SELECT c1, c2 FROM mpp_ft2 order by c1 limit 0 offset null;
EXPLAIN (VERBOSE, COSTS OFF)
SELECT c1, c2 FROM mpp_ft2 order by c1 limit 3 offset null;
EXPLAIN (VERBOSE, COSTS OFF)
SELECT c1, c2 FROM mpp_ft2 order by c1 limit 3 offset 0;
ALTER FOREIGN TABLE mpp_ft2 OPTIONS(set use_remote_estimate 'false');
-- Query with aggregates and limit clause together is NOT pushed down.
-- Because it's unsafe to do partial aggregate and limit in multiple remote servers.
EXPLAIN (VERBOSE, COSTS OFF)
SELECT count(c1), max(c6) FROM mpp_ft2 GROUP BY c2 order by c2 limit 3;
SELECT count(c1), max(c6) FROM mpp_ft2 GROUP BY c2 order by c2 limit 3;
-- ===================================================================
-- Queries with JOIN
-- ===================================================================
-- join is not safe to pushed down when there are multiple remote servers
EXPLAIN (VERBOSE, COSTS OFF)
SELECT count(*), sum(t1.c1), avg(t2.c2) FROM mpp_ft2 t1 inner join mpp_ft2 t2 on (t1.c1 = t2.c1) where t1.c1 = 2;
SELECT count(*), sum(t1.c1), avg(t2.c2) FROM mpp_ft2 t1 inner join mpp_ft2 t2 on (t1.c1 = t2.c1) where t1.c1 = 2;