From 11921b333bbd72a32d2f79812a38c6068f9c5de7 Mon Sep 17 00:00:00 2001 From: Jeevan Chalke Date: Mon, 24 Jun 2024 18:36:08 +0530 Subject: [PATCH] Add support for PostgreSQL 17 and EDB Postgres Advanced Server 17. Code changes involve adjusting calls to some server-side functions due to their signature changes. FDW-682, Suraj Kharage, reviewed by Jeevan Chalke. --- Makefile | 4 +- README.md | 2 +- expected/aggregate_pushdown_2.out | 1997 ++++++++++++++++++++++++ expected/join_pushdown_2.out | 2127 ++++++++++++++++++++++++++ expected/limit_offset_pushdown_1.out | 380 +++++ mongo_fdw.c | 151 +- 6 files changed, 4653 insertions(+), 8 deletions(-) create mode 100644 expected/aggregate_pushdown_2.out create mode 100644 expected/join_pushdown_2.out create mode 100644 expected/limit_offset_pushdown_1.out diff --git a/Makefile b/Makefile index f0e63d9..26dc848 100644 --- a/Makefile +++ b/Makefile @@ -42,6 +42,6 @@ ifndef MAJORVERSION MAJORVERSION := $(basename $(VERSION)) endif -ifeq (,$(findstring $(MAJORVERSION), 12 13 14 15 16)) - $(error PostgreSQL 12, 13, 14, 15, or 16 is required to compile this extension) +ifeq (,$(findstring $(MAJORVERSION), 12 13 14 15 16 17)) + $(error PostgreSQL 12, 13, 14, 15, 16, or 17 is required to compile this extension) endif diff --git a/README.md b/README.md index c403d94..b71c90f 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ This PostgreSQL extension implements a Foreign Data Wrapper (FDW) for [MongoDB][1]. Please note that this version of mongo_fdw works with PostgreSQL and EDB -Postgres Advanced Server 12, 13, 14, 15 and 16. +Postgres Advanced Server 12, 13, 14, 15, 16 and 17. PostgreSQL + MongoDB diff --git a/expected/aggregate_pushdown_2.out b/expected/aggregate_pushdown_2.out new file mode 100644 index 0000000..e968598 --- /dev/null +++ b/expected/aggregate_pushdown_2.out @@ -0,0 +1,1997 @@ +\set MONGO_HOST `echo \'"$MONGO_HOST"\'` +\set MONGO_PORT `echo \'"$MONGO_PORT"\'` +\set MONGO_USER_NAME `echo \'"$MONGO_USER_NAME"\'` +\set MONGO_PASS `echo \'"$MONGO_PWD"\'` +-- Before running this file user must create database mongo_fdw_regress on +-- MongoDB with all permission for MONGO_USER_NAME user with MONGO_PASS +-- password and ran mongodb_init.sh file to load collections. +\c contrib_regression +CREATE EXTENSION IF NOT EXISTS mongo_fdw; +CREATE SERVER mongo_server FOREIGN DATA WRAPPER mongo_fdw + OPTIONS (address :MONGO_HOST, port :MONGO_PORT); +CREATE USER MAPPING FOR public SERVER mongo_server; +-- Create foreign tables. +CREATE FOREIGN TABLE fdw137_t1 (_id NAME, c1 INTEGER, c2 TEXT, c3 CHAR(9), c4 INTEGER, c5 pg_catalog.Date, c6 DECIMAL, c7 INTEGER, c8 INTEGER) + SERVER mongo_server OPTIONS (database 'mongo_fdw_regress', collection 'test_tbl1'); +CREATE FOREIGN TABLE fdw137_t2 (_id NAME, c1 INTEGER, c2 TEXT, c3 TEXT) + SERVER mongo_server OPTIONS (database 'mongo_fdw_regress', collection 'test_tbl2'); +INSERT INTO fdw137_t1 VALUES (0, 1500, 'EMP15', 'FINANCE', 1300, '2000-12-25', 950.0, 400, 60); +INSERT INTO fdw137_t1 VALUES (0, 1600, 'EMP16', 'ADMIN', 600); +INSERT INTO fdw137_t2 VALUES (0, 50, 'TESTING', 'NASHIK'); +INSERT INTO fdw137_t2 VALUES (0); +-- Create local table. +CREATE TABLE fdw137_local AS + SELECT c1, c2, c3, c4, c5, c6, c7, c8 FROM fdw137_t1; +-- Simple aggregates. ORDER BY push-down not possible because only column names allowed. +EXPLAIN (VERBOSE, COSTS OFF) +SELECT count(*), sum(c1), avg(c1), min(c4), max(c1), sum(c1) * (random() <= 1)::int AS sum2 FROM fdw137_t1 WHERE c4 > 600 GROUP BY c4 ORDER BY 1 ASC NULLS FIRST, 2 ASC NULLS FIRST; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------ + Result + Output: (count(*)), (sum(c1)), (avg(c1)), (min(c4)), (max(c1)), ((sum(c1)) * ((random() <= '1'::double precision))::integer), c4 + -> Sort + Output: (count(*)), (sum(c1)), (avg(c1)), (min(c4)), (max(c1)), c4 + Sort Key: (count(*)) NULLS FIRST, (sum(fdw137_t1.c1)) NULLS FIRST + -> Foreign Scan + Output: (count(*)), (sum(c1)), (avg(c1)), (min(c4)), (max(c1)), c4 + Foreign Namespace: Aggregate on (mongo_fdw_regress.test_tbl1 fdw137_t1) +(8 rows) + +SELECT count(*), sum(c1), avg(c1), min(c4), max(c1), sum(c1) * (random() <= 1)::int AS sum2 FROM fdw137_t1 WHERE c4 > 600 GROUP BY c4 ORDER BY 1 ASC NULLS FIRST, 2 ASC NULLS FIRST; + count | sum | avg | min | max | sum2 +-------+------+------------------+------+------+------ + 1 | 1100 | 1100 | 800 | 1100 | 1100 + 1 | 1400 | 1400 | 700 | 1400 | 1400 + 2 | 1600 | 800 | 1300 | 1500 | 1600 + 3 | 1700 | 566.666666666667 | 900 | 700 | 1700 +(4 rows) + +-- GROUP BY clause HAVING expressions +EXPLAIN (VERBOSE, COSTS OFF) +SELECT c1, sum(c1), count(*) FROM fdw137_t1 GROUP BY c1 HAVING min(c1) > 500 ORDER BY c1 ASC NULLS FIRST; + QUERY PLAN +--------------------------------------------------------------------------- + Foreign Scan + Output: c1, (sum(c1)), (count(*)) + Foreign Namespace: Aggregate on (mongo_fdw_regress.test_tbl1 fdw137_t1) +(3 rows) + +SELECT c1, sum(c1), count(*) FROM fdw137_t1 GROUP BY c1 HAVING min(c1) > 500 ORDER BY c1 ASC NULLS FIRST; + c1 | sum | count +------+------+------- + 600 | 600 | 1 + 700 | 700 | 1 + 800 | 800 | 1 + 900 | 900 | 1 + 1000 | 1000 | 1 + 1100 | 1100 | 1 + 1200 | 1200 | 1 + 1300 | 1300 | 1 + 1400 | 1400 | 1 + 1500 | 1500 | 1 + 1600 | 1600 | 1 +(11 rows) + +EXPLAIN (VERBOSE, COSTS OFF) +SELECT c8, min(c2) FROM fdw137_t1 WHERE c3 = 'ADMIN' GROUP BY c8 HAVING min(c8) = 20 ORDER BY c8 ASC NULLS FIRST; + QUERY PLAN +--------------------------------------------------------------------------- + Foreign Scan + Output: c8, (min(c2)) + Foreign Namespace: Aggregate on (mongo_fdw_regress.test_tbl1 fdw137_t1) +(3 rows) + +SELECT c8, min(c2) FROM fdw137_t1 WHERE c3 = 'ADMIN' GROUP BY c8 HAVING min(c8) = 20 ORDER BY c8 ASC NULLS FIRST; + c8 | min +----+------ + 20 | EMP1 +(1 row) + +-- Multi-column GROUP BY clause. Push-down. +EXPLAIN (VERBOSE, COSTS OFF) +SELECT c2, sum(c1) FROM fdw137_t1 GROUP BY c1, c2 HAVING min(c1) > 500 ORDER BY 1 ASC NULLS FIRST; + QUERY PLAN +--------------------------------------------------------------------------- + Foreign Scan + Output: c2, (sum(c1)), c1 + Foreign Namespace: Aggregate on (mongo_fdw_regress.test_tbl1 fdw137_t1) +(3 rows) + +SELECT c2, sum(c1) FROM fdw137_t1 GROUP BY c1, c2 HAVING min(c1) > 500 ORDER BY 1 ASC NULLS FIRST; + c2 | sum +-------+------ + EMP10 | 1000 + EMP11 | 1100 + EMP12 | 1200 + EMP13 | 1300 + EMP14 | 1400 + EMP15 | 1500 + EMP16 | 1600 + EMP6 | 600 + EMP7 | 700 + EMP8 | 800 + EMP9 | 900 +(11 rows) + +-- With ORDER BY pushdown disabled. +SET mongo_fdw.enable_order_by_pushdown TO OFF; +EXPLAIN (VERBOSE, COSTS OFF) +SELECT c2, sum(c1) FROM fdw137_t1 GROUP BY c1, c2 HAVING min(c1) > 500 ORDER BY 1 ASC NULLS FIRST; + QUERY PLAN +--------------------------------------------------------------------------------- + Sort + Output: c2, (sum(c1)), c1 + Sort Key: fdw137_t1.c2 NULLS FIRST + -> Foreign Scan + Output: c2, (sum(c1)), c1 + Foreign Namespace: Aggregate on (mongo_fdw_regress.test_tbl1 fdw137_t1) +(6 rows) + +SELECT c2, sum(c1) FROM fdw137_t1 GROUP BY c1, c2 HAVING min(c1) > 500 ORDER BY 1 ASC NULLS FIRST; + c2 | sum +-------+------ + EMP10 | 1000 + EMP11 | 1100 + EMP12 | 1200 + EMP13 | 1300 + EMP14 | 1400 + EMP15 | 1500 + EMP16 | 1600 + EMP6 | 600 + EMP7 | 700 + EMP8 | 800 + EMP9 | 900 +(11 rows) + +SET mongo_fdw.enable_order_by_pushdown TO ON; +-- Aggregation on expression. Don't push-down. +EXPLAIN (VERBOSE, COSTS OFF) +SELECT c1, sum(c1+2) FROM fdw137_t1 GROUP BY c1 HAVING min(c1) > 500 ORDER BY c1 ASC NULLS FIRST; + QUERY PLAN +-------------------------------------------------------- + GroupAggregate + Output: c1, sum((c1 + 2)) + Group Key: fdw137_t1.c1 + Filter: (min(fdw137_t1.c1) > 500) + -> Foreign Scan on public.fdw137_t1 + Output: _id, c1, c2, c3, c4, c5, c6, c7, c8 + Foreign Namespace: mongo_fdw_regress.test_tbl1 +(7 rows) + +SELECT c1, sum(c1+2) FROM fdw137_t1 GROUP BY c1 HAVING min(c1) > 500 ORDER BY c1 ASC NULLS FIRST; + c1 | sum +------+------ + 600 | 602 + 700 | 702 + 800 | 802 + 900 | 902 + 1000 | 1002 + 1100 | 1102 + 1200 | 1202 + 1300 | 1302 + 1400 | 1402 + 1500 | 1502 + 1600 | 1602 +(11 rows) + +-- Aggregate with unshippable GROUP BY clause are not pushed +EXPLAIN (VERBOSE, COSTS OFF) +SELECT avg(c4) FROM fdw137_t1 GROUP BY c4 * (random() <= 1)::int ORDER BY 1; + QUERY PLAN +------------------------------------------------------------------------------------ + Sort + Output: (avg(c4)), ((c4 * ((random() <= '1'::double precision))::integer)) + Sort Key: (avg(fdw137_t1.c4)) + -> HashAggregate + Output: avg(c4), ((c4 * ((random() <= '1'::double precision))::integer)) + Group Key: (fdw137_t1.c4 * ((random() <= '1'::double precision))::integer) + -> Foreign Scan on public.fdw137_t1 + Output: (c4 * ((random() <= '1'::double precision))::integer), c4 + Foreign Namespace: mongo_fdw_regress.test_tbl1 +(9 rows) + +SELECT avg(c4) FROM fdw137_t1 GROUP BY c4 * (random() <= 1)::int ORDER BY 1; + avg +----------------------- + 400.0000000000000000 + 600.0000000000000000 + 700.0000000000000000 + 800.0000000000000000 + 900.0000000000000000 + 1300.0000000000000000 + +(7 rows) + +EXPLAIN (VERBOSE, COSTS OFF) +SELECT c1, sum(c1) FROM fdw137_t1 GROUP BY c1 HAVING min(c1 * 3) > 500 ORDER BY c1; + QUERY PLAN +-------------------------------------------------------------- + Sort + Output: c1, (sum(c1)) + Sort Key: fdw137_t1.c1 + -> HashAggregate + Output: c1, sum(c1) + Group Key: fdw137_t1.c1 + Filter: (min((fdw137_t1.c1 * 3)) > 500) + -> Foreign Scan on public.fdw137_t1 + Output: _id, c1, c2, c3, c4, c5, c6, c7, c8 + Foreign Namespace: mongo_fdw_regress.test_tbl1 +(10 rows) + +SELECT c1, sum(c1) FROM fdw137_t1 GROUP BY c1 HAVING min(c1 * 3) > 500 ORDER BY c1; + c1 | sum +------+------ + 200 | 200 + 300 | 300 + 400 | 400 + 500 | 500 + 600 | 600 + 700 | 700 + 800 | 800 + 900 | 900 + 1000 | 1000 + 1100 | 1100 + 1200 | 1200 + 1300 | 1300 + 1400 | 1400 + 1500 | 1500 + 1600 | 1600 +(15 rows) + +-- FDW-134: Test ORDER BY with COLLATE. Shouldn't push-down +EXPLAIN (VERBOSE, COSTS OFF) +SELECT c2, sum(c1) FROM fdw137_t1 GROUP BY c1, c2 HAVING min(c1) > 500 ORDER BY c2 COLLATE "en_US" ASC NULLS FIRST; + QUERY PLAN +--------------------------------------------------------------------------------- + Sort + Output: c2, (sum(c1)), ((c2)::text), c1 + Sort Key: fdw137_t1.c2 COLLATE "en_US" NULLS FIRST + -> Foreign Scan + Output: c2, (sum(c1)), c2, c1 + Foreign Namespace: Aggregate on (mongo_fdw_regress.test_tbl1 fdw137_t1) +(6 rows) + +SELECT c2, sum(c1) FROM fdw137_t1 GROUP BY c1, c2 HAVING min(c1) > 500 ORDER BY c2 COLLATE "en_US" ASC NULLS FIRST; + c2 | sum +-------+------ + EMP10 | 1000 + EMP11 | 1100 + EMP12 | 1200 + EMP13 | 1300 + EMP14 | 1400 + EMP15 | 1500 + EMP16 | 1600 + EMP6 | 600 + EMP7 | 700 + EMP8 | 800 + EMP9 | 900 +(11 rows) + +-- Using expressions in HAVING clause. Pushed down. +EXPLAIN (VERBOSE, COSTS OFF) +SELECT c3, count(*) FROM fdw137_t1 GROUP BY c3 HAVING abs(max(c8)) = abs(10) ORDER BY 1, 2; + QUERY PLAN +--------------------------------------------------------------------------------- + Sort + Output: c3, (count(*)) + Sort Key: fdw137_t1.c3, (count(*)) + -> Foreign Scan + Output: c3, (count(*)) + Filter: (abs((max(fdw137_t1.c8))) = 10) + Foreign Namespace: Aggregate on (mongo_fdw_regress.test_tbl1 fdw137_t1) +(7 rows) + +SELECT c3, count(*) FROM fdw137_t1 GROUP BY c3 HAVING abs(max(c8)) = abs(10) ORDER BY 1, 2; + c3 | count +-----------+------- + HEAD | 1 +(1 row) + +-- Unshippable HAVING clause will be evaluated locally, and other qual in HAVING clause is pushed down +EXPLAIN (VERBOSE, COSTS OFF) +SELECT count(*) FROM (SELECT c3, count(c1) FROM fdw137_t1 GROUP BY c3 HAVING (avg(c1) / avg(c1)) * random() <= 1 and min(c1) > 100) x; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------- + Aggregate + Output: count(*) + -> Foreign Scan + Output: fdw137_t1.c3, NULL::bigint + Filter: (((((avg(fdw137_t1.c1)) / (avg(fdw137_t1.c1))))::double precision * random()) <= '1'::double precision) + Foreign Namespace: Aggregate on (mongo_fdw_regress.test_tbl1 fdw137_t1) +(6 rows) + +SELECT count(*) FROM (SELECT c3, count(c1) FROM fdw137_t1 GROUP BY c3 HAVING (avg(c1) / avg(c1)) * random() <= 1 and min(c1) > 100) x; + count +------- + 0 +(1 row) + +-- Aggregate over join query +EXPLAIN (VERBOSE, COSTS OFF) +SELECT sum(t1.c8), avg(t2.c1) FROM fdw137_t1 t1 INNER JOIN fdw137_t2 t2 ON (t1.c8 = t2.c1) WHERE t1.c8%2 = 0 ORDER BY 1 DESC NULLS LAST; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------ + Sort + Output: (sum(t1.c8)), (avg(t2.c1)) + Sort Key: (sum(t1.c8)) DESC NULLS LAST + -> Foreign Scan + Output: (sum(t1.c8)), (avg(t2.c1)) + Foreign Namespace: Aggregate on ((mongo_fdw_regress.test_tbl1 t1) INNER JOIN (mongo_fdw_regress.test_tbl2 t2)) +(6 rows) + +SELECT sum(t1.c8), avg(t2.c1) FROM fdw137_t1 t1 INNER JOIN fdw137_t2 t2 ON (t1.c8 = t2.c1) WHERE t1.c8%2 = 0 ORDER BY 1 DESC NULLS LAST; + sum | avg +-----+------------------ + 310 | 22.1428571428571 +(1 row) + +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.c1, count(*), t2.c4 FROM fdw137_t2 t1 INNER JOIN fdw137_t1 t2 ON (t1.c1 = t2.c8) GROUP BY t1.c1, t2.c4 ORDER BY 1 ASC NULLS FIRST, 3 ASC NULLS FIRST; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------ + Foreign Scan + Output: t1.c1, (count(*)), t2.c4 + Foreign Namespace: Aggregate on ((mongo_fdw_regress.test_tbl2 t1) INNER JOIN (mongo_fdw_regress.test_tbl1 t2)) +(3 rows) + +SELECT t1.c1, count(*), t2.c4 FROM fdw137_t2 t1 INNER JOIN fdw137_t1 t2 ON (t1.c1 = t2.c8) GROUP BY t1.c1, t2.c4 ORDER BY 1 ASC NULLS FIRST, 3 ASC NULLS FIRST; + c1 | count | c4 +----+-------+------ + 10 | 1 | + 10 | 1 | 700 + 10 | 1 | 900 + 20 | 2 | 400 + 20 | 1 | 800 + 20 | 1 | 900 + 20 | 1 | 1300 + 30 | 5 | 600 + 30 | 1 | 900 +(9 rows) + +EXPLAIN (VERBOSE, COSTS OFF) +SELECT sum(t2.c1), t1.c8, avg(t1.c8) FROM fdw137_t1 t1 LEFT JOIN fdw137_t2 t2 ON (t1.c8 = t2.c1) WHERE t1.c8 > 10 GROUP BY t1.c8 HAVING avg(t1.c8)*1 > 10 ORDER BY 2 ASC NULLS FIRST; + QUERY PLAN +----------------------------------------------------------------------------------------------------------------- + Foreign Scan + Output: (sum(t2.c1)), t1.c8, (avg(t1.c8)) + Foreign Namespace: Aggregate on ((mongo_fdw_regress.test_tbl1 t1) LEFT JOIN (mongo_fdw_regress.test_tbl2 t2)) +(3 rows) + +SELECT sum(t2.c1), t1.c8, avg(t1.c8) FROM fdw137_t1 t1 LEFT JOIN fdw137_t2 t2 ON (t1.c8 = t2.c1) WHERE t1.c8 > 10 GROUP BY t1.c8 HAVING avg(t1.c8)*1 > 10 ORDER BY 2 ASC NULLS FIRST; + sum | c8 | avg +-----+----+----- + 100 | 20 | 20 + 180 | 30 | 30 + 0 | 60 | 60 +(3 rows) + +-- With ORDER BY pushdown disabled. +SET mongo_fdw.enable_order_by_pushdown TO OFF; +EXPLAIN (VERBOSE, COSTS OFF) +SELECT sum(t2.c1), t1.c8, avg(t1.c8) FROM fdw137_t1 t1 LEFT JOIN fdw137_t2 t2 ON (t1.c8 = t2.c1) WHERE t1.c8 > 10 GROUP BY t1.c8 HAVING avg(t1.c8)*1 > 10 ORDER BY 2 ASC NULLS FIRST; + QUERY PLAN +----------------------------------------------------------------------------------------------------------------------- + Sort + Output: (sum(t2.c1)), t1.c8, (avg(t1.c8)) + Sort Key: t1.c8 NULLS FIRST + -> Foreign Scan + Output: (sum(t2.c1)), t1.c8, (avg(t1.c8)) + Foreign Namespace: Aggregate on ((mongo_fdw_regress.test_tbl1 t1) LEFT JOIN (mongo_fdw_regress.test_tbl2 t2)) +(6 rows) + +SELECT sum(t2.c1), t1.c8, avg(t1.c8) FROM fdw137_t1 t1 LEFT JOIN fdw137_t2 t2 ON (t1.c8 = t2.c1) WHERE t1.c8 > 10 GROUP BY t1.c8 HAVING avg(t1.c8)*1 > 10 ORDER BY 2 ASC NULLS FIRST; + sum | c8 | avg +-----+----+----- + 100 | 20 | 20 + 180 | 30 | 30 + 0 | 60 | 60 +(3 rows) + +SET mongo_fdw.enable_order_by_pushdown TO ON; +-- Aggregate is not pushed down as aggregation contains random() +EXPLAIN (VERBOSE, COSTS OFF) +SELECT sum(c1 * (random() <= 1)::int) AS sum, avg(c1) FROM fdw137_t1 ORDER BY 1; + QUERY PLAN +------------------------------------------------------------------------------------- + Sort + Output: (sum((c1 * ((random() <= '1'::double precision))::integer))), (avg(c1)) + Sort Key: (sum((fdw137_t1.c1 * ((random() <= '1'::double precision))::integer))) + -> Aggregate + Output: sum((c1 * ((random() <= '1'::double precision))::integer)), avg(c1) + -> Foreign Scan on public.fdw137_t1 + Output: _id, c1, c2, c3, c4, c5, c6, c7, c8 + Foreign Namespace: mongo_fdw_regress.test_tbl1 +(8 rows) + +SELECT sum(c1 * (random() <= 1)::int) AS sum, avg(c1) FROM fdw137_t1 ORDER BY 1; + sum | avg +-------+---------------------- + 13600 | 850.0000000000000000 +(1 row) + +-- Not pushed down due to local conditions present in underneath input rel +EXPLAIN (VERBOSE, COSTS OFF) +SELECT sum(t1.c8) FROM fdw137_t1 t1 INNER JOIN fdw137_t2 t2 ON (t1.c8 = t2.c1) WHERE ((t1.c8 * t2.c1)/(t1.c8 * t2.c1)) * random() <= 1 ORDER BY 1; + QUERY PLAN +----------------------------------------------------------------------------------------------------------------------- + Sort + Output: (sum(t1.c8)) + Sort Key: (sum(t1.c8)) + -> Aggregate + Output: sum(t1.c8) + -> Foreign Scan + Output: t1.c8 + Filter: (((((t1.c8 * t2.c1) / (t1.c8 * t2.c1)))::double precision * random()) <= '1'::double precision) + Foreign Namespace: (mongo_fdw_regress.test_tbl1 t1) INNER JOIN (mongo_fdw_regress.test_tbl2 t2) +(9 rows) + +SELECT sum(t1.c8) FROM fdw137_t1 t1 INNER JOIN fdw137_t2 t2 ON (t1.c8 = t2.c1) WHERE ((t1.c8 * t2.c1)/(t1.c8 * t2.c1)) * random() <= 1 ORDER BY 1; + sum +----- + 310 +(1 row) + +-- Aggregates in subquery are pushed down. +EXPLAIN (VERBOSE, COSTS OFF) +SELECT count(x.a), sum(x.a) FROM (SELECT c8 a, sum(c1) b FROM fdw137_t1 GROUP BY c8 ORDER BY 1, 2) x; + QUERY PLAN +--------------------------------------------------------------------------------------- + Aggregate + Output: count(fdw137_t1.c8), sum(fdw137_t1.c8) + -> Sort + Output: fdw137_t1.c8, (sum(fdw137_t1.c1)) + Sort Key: fdw137_t1.c8, (sum(fdw137_t1.c1)) + -> Foreign Scan + Output: fdw137_t1.c8, (sum(fdw137_t1.c1)) + Foreign Namespace: Aggregate on (mongo_fdw_regress.test_tbl1 fdw137_t1) +(8 rows) + +SELECT count(x.a), sum(x.a) FROM (SELECT c8 a, sum(c1) b FROM fdw137_t1 GROUP BY c8 ORDER BY 1, 2) x; + count | sum +-------+----- + 4 | 120 +(1 row) + +-- Aggregate is still pushed down by taking unshippable expression out +EXPLAIN (VERBOSE, COSTS OFF) +SELECT c4 * (random() <= 1)::int AS sum1, sum(c1) AS sum2 FROM fdw137_t1 GROUP BY c4 ORDER BY 1, 2; + QUERY PLAN +---------------------------------------------------------------------------------------------------- + Sort + Output: ((c4 * ((random() <= '1'::double precision))::integer)), (sum(c1)), c4 + Sort Key: ((fdw137_t1.c4 * ((random() <= '1'::double precision))::integer)), (sum(fdw137_t1.c1)) + -> Foreign Scan + Output: (c4 * ((random() <= '1'::double precision))::integer), (sum(c1)), c4 + Foreign Namespace: Aggregate on (mongo_fdw_regress.test_tbl1 fdw137_t1) +(6 rows) + +SELECT c4 * (random() <= 1)::int AS sum1, sum(c1) AS sum2 FROM fdw137_t1 GROUP BY c4 ORDER BY 1, 2; + sum1 | sum2 +------+------ + 400 | 2100 + 600 | 4800 + 700 | 1400 + 800 | 1100 + 900 | 1700 + 1300 | 1600 + | 900 +(7 rows) + +-- Testing ORDER BY, DISTINCT, FILTER and Ordered-sets within aggregates +-- ORDER BY within aggregates (same column used to order) are not pushed +EXPLAIN (VERBOSE, COSTS OFF) +SELECT sum(c1 ORDER BY c1) FROM fdw137_t1 WHERE c1 < 500 GROUP BY c2 ORDER BY 1; + QUERY PLAN +-------------------------------------------------------------------- + Sort + Output: (sum(c1 ORDER BY c1)), c2 + Sort Key: (sum(fdw137_t1.c1 ORDER BY fdw137_t1.c1)) + -> GroupAggregate + Output: sum(c1 ORDER BY c1), c2 + Group Key: fdw137_t1.c2 + -> Sort + Output: c2, c1 + Sort Key: fdw137_t1.c2, fdw137_t1.c1 + -> Foreign Scan on public.fdw137_t1 + Output: c2, c1 + Foreign Namespace: mongo_fdw_regress.test_tbl1 +(12 rows) + +SELECT sum(c1 ORDER BY c1) FROM fdw137_t1 WHERE c1 < 500 GROUP BY c2 ORDER BY 1; + sum +----- + 100 + 200 + 300 + 400 +(4 rows) + +-- ORDER BY within aggregate (different column used to order also using DESC) +-- are not pushed. +EXPLAIN (VERBOSE, COSTS OFF) +SELECT sum(c8 ORDER BY c1 desc) FROM fdw137_t1 WHERE c1 > 1000 and c8 > 20; + QUERY PLAN +-------------------------------------------------------------- + Aggregate + Output: sum(c8 ORDER BY c1 DESC) + -> Sort + Output: c8, c1 + Sort Key: fdw137_t1.c1 DESC + -> Foreign Scan on public.fdw137_t1 + Output: c8, c1 + Foreign Namespace: mongo_fdw_regress.test_tbl1 +(8 rows) + +SELECT sum(c8 ORDER BY c1 desc) FROM fdw137_t1 WHERE c1 > 1000 and c8 > 20; + sum +----- + 90 +(1 row) + +-- DISTINCT within aggregate. Don't push down. +EXPLAIN (VERBOSE, COSTS OFF) +SELECT sum(DISTINCT (c1)) FROM fdw137_t1 WHERE c4 = 600 and c1 < 500; + QUERY PLAN +-------------------------------------------------------------- + Aggregate + Output: sum(DISTINCT c1) + -> Sort + Output: c1 + Sort Key: fdw137_t1.c1 + -> Foreign Scan on public.fdw137_t1 + Output: c1 + Foreign Namespace: mongo_fdw_regress.test_tbl1 +(8 rows) + +SELECT sum(DISTINCT (c1)) FROM fdw137_t1 WHERE c4 = 600 and c1 < 500; + sum +----- + 500 +(1 row) + +EXPLAIN (VERBOSE, COSTS OFF) +SELECT sum(DISTINCT (t1.c1)) FROM fdw137_t1 t1 join fdw137_t2 t2 ON (t1.c8 = t2.c1) WHERE t1.c8 < 30 GROUP BY (t2.c1) ORDER BY 1; + QUERY PLAN +--------------------------------------------------------------------------------------------------------------------- + Sort + Output: (sum(DISTINCT t1.c1)), t2.c1 + Sort Key: (sum(DISTINCT t1.c1)) + -> GroupAggregate + Output: sum(DISTINCT t1.c1), t2.c1 + Group Key: t2.c1 + -> Sort + Output: t2.c1, t1.c1 + Sort Key: t2.c1, t1.c1 + -> Foreign Scan + Output: t2.c1, t1.c1 + Foreign Namespace: (mongo_fdw_regress.test_tbl1 t1) INNER JOIN (mongo_fdw_regress.test_tbl2 t2) +(12 rows) + +SELECT sum(DISTINCT (t1.c1)) FROM fdw137_t1 t1 join fdw137_t2 t2 ON (t1.c8 = t2.c1) WHERE t1.c8 < 30 GROUP BY (t2.c1) ORDER BY 1; + sum +------ + 3000 + 3700 +(2 rows) + +-- DISTINCT, ORDER BY and FILTER within aggregate, not pushed down. +EXPLAIN (VERBOSE, COSTS OFF) +SELECT sum(c1), sum(DISTINCT c1 ORDER BY c1) filter (WHERE c1%3 < 2), c4 FROM fdw137_t1 WHERE c4 = 600 GROUP BY c4; + QUERY PLAN +----------------------------------------------------------------------------------- + GroupAggregate + Output: sum(c1), sum(DISTINCT c1 ORDER BY c1) FILTER (WHERE ((c1 % 3) < 2)), c4 + -> Sort + Output: c1, c4 + Sort Key: fdw137_t1.c1 + -> Foreign Scan on public.fdw137_t1 + Output: c1, c4 + Foreign Namespace: mongo_fdw_regress.test_tbl1 +(8 rows) + +SELECT sum(c1), sum(DISTINCT c1 ORDER BY c1) filter (WHERE c1%3 < 2), c4 FROM fdw137_t1 WHERE c4 = 600 GROUP BY c4; + sum | sum | c4 +------+------+----- + 4800 | 4100 | 600 +(1 row) + +-- FILTER within aggregate, not pushed +EXPLAIN (VERBOSE, COSTS OFF) +SELECT sum(c1) filter (WHERE c1 < 1000 and c4 > 500) FROM fdw137_t1 GROUP BY c4 ORDER BY 1 nulls last; + QUERY PLAN +------------------------------------------------------------------------------------------------- + Sort + Output: (sum(c1) FILTER (WHERE ((c1 < 1000) AND (c4 > 500)))), c4 + Sort Key: (sum(fdw137_t1.c1) FILTER (WHERE ((fdw137_t1.c1 < 1000) AND (fdw137_t1.c4 > 500)))) + -> HashAggregate + Output: sum(c1) FILTER (WHERE ((c1 < 1000) AND (c4 > 500))), c4 + Group Key: fdw137_t1.c4 + -> Foreign Scan on public.fdw137_t1 + Output: _id, c1, c2, c3, c4, c5, c6, c7, c8 + Foreign Namespace: mongo_fdw_regress.test_tbl1 +(9 rows) + +SELECT sum(c1) filter (WHERE c1 < 1000 and c4 > 500) FROM fdw137_t1 GROUP BY c4 ORDER BY 1 nulls last; + sum +------ + 100 + 1000 + 1700 + + + + +(7 rows) + +-- Outer query is aggregation query +EXPLAIN (VERBOSE, COSTS OFF) +SELECT DISTINCT (SELECT count(*) filter (WHERE t2.c1 = 20 and t2.c1 < 30) FROM fdw137_t1 t1 WHERE t1.c1 = 500) FROM fdw137_t2 t2 ORDER BY 1; + QUERY PLAN +--------------------------------------------------------------------------------------- + Unique + Output: ((SubPlan 1)) + -> Sort + Output: ((SubPlan 1)) + Sort Key: ((SubPlan 1)) + -> Aggregate + Output: (SubPlan 1) + -> Foreign Scan on public.fdw137_t2 t2 + Output: t2._id, t2.c1, t2.c2, t2.c3 + Foreign Namespace: mongo_fdw_regress.test_tbl2 + SubPlan 1 + -> Foreign Scan on public.fdw137_t1 t1 + Output: count(*) FILTER (WHERE ((t2.c1 = 20) AND (t2.c1 < 30))) + Foreign Namespace: mongo_fdw_regress.test_tbl1 +(14 rows) + +SELECT DISTINCT (SELECT count(*) filter (WHERE t2.c1 = 20 and t2.c1 < 30) FROM fdw137_t1 t1 WHERE t1.c1 = 500) FROM fdw137_t2 t2 ORDER BY 1; + count +------- + 1 +(1 row) + +-- Inner query is aggregation query +EXPLAIN (VERBOSE, COSTS OFF) +SELECT DISTINCT (SELECT count(t1.c1) filter (WHERE t2.c1 = 20 and t2.c1 < 30) FROM fdw137_t1 t1 WHERE t1.c1 > 600) FROM fdw137_t2 t2 ORDER BY 1; + QUERY PLAN +---------------------------------------------------------------------------------------------------- + Unique + Output: ((SubPlan 1)) + -> Sort + Output: ((SubPlan 1)) + Sort Key: ((SubPlan 1)) + -> Foreign Scan on public.fdw137_t2 t2 + Output: (SubPlan 1) + Foreign Namespace: mongo_fdw_regress.test_tbl2 + SubPlan 1 + -> Aggregate + Output: count(t1.c1) FILTER (WHERE ((t2.c1 = 20) AND (t2.c1 < 30))) + -> Foreign Scan on public.fdw137_t1 t1 + Output: t1._id, t1.c1, t1.c2, t1.c3, t1.c4, t1.c5, t1.c6, t1.c7, t1.c8 + Foreign Namespace: mongo_fdw_regress.test_tbl1 +(14 rows) + +SELECT DISTINCT (SELECT count(t1.c1) filter (WHERE t2.c1 = 20 and t2.c1 < 30) FROM fdw137_t1 t1 WHERE t1.c1 > 600) FROM fdw137_t2 t2 ORDER BY 1; + count +------- + 0 + 10 +(2 rows) + +-- Ordered-sets within aggregate, not pushed down. +EXPLAIN (VERBOSE, COSTS OFF) +SELECT c8, rank('10'::varchar) within group (ORDER BY c3), percentile_cont(c8/200::numeric) within group (ORDER BY c1) FROM fdw137_t1 GROUP BY c8 HAVING percentile_cont(c8/200::numeric) within group (ORDER BY c1) < 500 ORDER BY c8; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + GroupAggregate + Output: c8, rank('10'::bpchar) WITHIN GROUP (ORDER BY c3), percentile_cont((((c8)::numeric / '200'::numeric))::double precision) WITHIN GROUP (ORDER BY ((c1)::double precision)) + Group Key: fdw137_t1.c8 + Filter: (percentile_cont((((fdw137_t1.c8)::numeric / '200'::numeric))::double precision) WITHIN GROUP (ORDER BY ((fdw137_t1.c1)::double precision)) < '500'::double precision) + -> Sort + Output: c8, c3, c1 + Sort Key: fdw137_t1.c8 + -> Foreign Scan on public.fdw137_t1 + Output: c8, c3, c1 + Foreign Namespace: mongo_fdw_regress.test_tbl1 +(10 rows) + +SELECT c8, rank('10'::varchar) within group (ORDER BY c3), percentile_cont(c8/200::numeric) within group (ORDER BY c1) FROM fdw137_t1 GROUP BY c8 HAVING percentile_cont(c8/200::numeric) within group (ORDER BY c1) < 500 ORDER BY c8; + c8 | rank | percentile_cont +----+------+----------------- + 20 | 1 | 220 + 30 | 1 | 275 +(2 rows) + +-- Subquery in FROM clause HAVING aggregate +EXPLAIN (VERBOSE, COSTS OFF) +SELECT count(*), x.b FROM fdw137_t1, (SELECT c1 a, sum(c1) b FROM fdw137_t2 GROUP BY c1) x WHERE fdw137_t1.c8 = x.a GROUP BY x.b ORDER BY 1, 2; + QUERY PLAN +----------------------------------------------------------------------------------------------------------------------------------------------------------- + Sort + Output: (count(*)), x.b + Sort Key: (count(*)), x.b + -> HashAggregate + Output: count(*), x.b + Group Key: x.b + -> Hash Join + Output: x.b + Inner Unique: true + Hash Cond: (fdw137_t1.c8 = x.a) + -> Foreign Scan on public.fdw137_t1 + Output: fdw137_t1._id, fdw137_t1.c1, fdw137_t1.c2, fdw137_t1.c3, fdw137_t1.c4, fdw137_t1.c5, fdw137_t1.c6, fdw137_t1.c7, fdw137_t1.c8 + Foreign Namespace: mongo_fdw_regress.test_tbl1 + -> Hash + Output: x.b, x.a + -> Subquery Scan on x + Output: x.b, x.a + -> Foreign Scan + Output: fdw137_t2.c1, (sum(fdw137_t2.c1)) + Foreign Namespace: Aggregate on (mongo_fdw_regress.test_tbl2 fdw137_t2) +(20 rows) + +SELECT count(*), x.b FROM fdw137_t1, (SELECT c1 a, sum(c1) b FROM fdw137_t2 GROUP BY c1) x WHERE fdw137_t1.c8 = x.a GROUP BY x.b ORDER BY 1, 2; + count | b +-------+---- + 3 | 10 + 5 | 20 + 6 | 30 +(3 rows) + +-- Join with IS NULL check in HAVING +EXPLAIN (VERBOSE, COSTS OFF) +SELECT avg(t1.c1), sum(t2.c1) FROM fdw137_t1 t1 join fdw137_t2 t2 ON (t1.c8 = t2.c1) GROUP BY t2.c1 HAVING avg(t1.c1) is null ORDER BY 1 nulls last, 2; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------ + Sort + Output: (avg(t1.c1)), (sum(t2.c1)), t2.c1 + Sort Key: (avg(t1.c1)), (sum(t2.c1)) + -> Foreign Scan + Output: (avg(t1.c1)), (sum(t2.c1)), t2.c1 + Filter: ((avg(t1.c1)) IS NULL) + Foreign Namespace: Aggregate on ((mongo_fdw_regress.test_tbl1 t1) INNER JOIN (mongo_fdw_regress.test_tbl2 t2)) +(7 rows) + +SELECT avg(t1.c1), sum(t2.c1) FROM fdw137_t1 t1 join fdw137_t2 t2 ON (t1.c8 = t2.c1) GROUP BY t2.c1 HAVING avg(t1.c1) is null ORDER BY 1 nulls last, 2; + avg | sum +-----+----- +(0 rows) + +-- ORDER BY expression is part of the target list but not pushed down to +-- foreign server. +EXPLAIN (VERBOSE, COSTS OFF) +SELECT sum(c1) * (random() <= 1)::int AS sum FROM fdw137_t1 ORDER BY 1; + QUERY PLAN +-------------------------------------------------------------------------------------- + Sort + Output: (((sum(c1)) * ((random() <= '1'::double precision))::integer)) + Sort Key: (((sum(fdw137_t1.c1)) * ((random() <= '1'::double precision))::integer)) + -> Foreign Scan + Output: ((sum(c1)) * ((random() <= '1'::double precision))::integer) + Foreign Namespace: Aggregate on (mongo_fdw_regress.test_tbl1 fdw137_t1) +(6 rows) + +SELECT sum(c1) * (random() <= 1)::int AS sum FROM fdw137_t1 ORDER BY 1; + sum +------- + 13600 +(1 row) + +-- LATERAL join, with parameterization +EXPLAIN (VERBOSE, COSTS OFF) +SELECT c8, sum FROM fdw137_t1 t1, lateral (SELECT sum(t2.c1) sum FROM fdw137_t2 t2 GROUP BY t2.c1) qry WHERE t1.c8 * 2 = qry.sum ORDER BY 1; + QUERY PLAN +-------------------------------------------------------------------------------------------- + Sort + Output: t1.c8, qry.sum + Sort Key: t1.c8 + -> Hash Join + Output: t1.c8, qry.sum + Hash Cond: ((t1.c8 * 2) = qry.sum) + -> Foreign Scan on public.fdw137_t1 t1 + Output: t1._id, t1.c1, t1.c2, t1.c3, t1.c4, t1.c5, t1.c6, t1.c7, t1.c8 + Foreign Namespace: mongo_fdw_regress.test_tbl1 + -> Hash + Output: qry.sum + -> Subquery Scan on qry + Output: qry.sum + -> Foreign Scan + Output: (sum(t2.c1)), t2.c1 + Foreign Namespace: Aggregate on (mongo_fdw_regress.test_tbl2 t2) +(16 rows) + +-- Check with placeHolderVars +EXPLAIN (VERBOSE, COSTS OFF) +SELECT q.b, count(fdw137_t1.c1), sum(q.a) FROM fdw137_t1 left join (SELECT min(13), avg(fdw137_t1.c1), sum(fdw137_t2.c1) FROM fdw137_t1 right join fdw137_t2 ON (fdw137_t1.c8 = fdw137_t2.c1) WHERE fdw137_t1.c8 = 20) q(a, b, c) ON (fdw137_t1.c8 = q.b) WHERE fdw137_t1.c1 between 100 and 500 GROUP BY q.b ORDER BY 1 nulls last, 2; + QUERY PLAN +----------------------------------------------------------------------------------------------------------------------------------------------------------------- + Incremental Sort + Output: q.b, (count(fdw137_t1.c1)), (sum(q.a)) + Sort Key: q.b, (count(fdw137_t1.c1)) + Presorted Key: q.b + -> GroupAggregate + Output: q.b, count(fdw137_t1.c1), sum(q.a) + Group Key: q.b + -> Sort + Output: q.b, fdw137_t1.c1, q.a + Sort Key: q.b + -> Hash Left Join + Output: q.b, fdw137_t1.c1, q.a + Inner Unique: true + Hash Cond: ((fdw137_t1.c8)::numeric = q.b) + -> Foreign Scan on public.fdw137_t1 + Output: fdw137_t1._id, fdw137_t1.c1, fdw137_t1.c2, fdw137_t1.c3, fdw137_t1.c4, fdw137_t1.c5, fdw137_t1.c6, fdw137_t1.c7, fdw137_t1.c8 + Foreign Namespace: mongo_fdw_regress.test_tbl1 + -> Hash + Output: q.b, q.a + -> Subquery Scan on q + Output: q.b, q.a + -> Aggregate + Output: min(13), avg(fdw137_t1_1.c1), NULL::bigint + -> Foreign Scan + Output: fdw137_t1_1.c1 + Foreign Namespace: (mongo_fdw_regress.test_tbl1 fdw137_t1) INNER JOIN (mongo_fdw_regress.test_tbl2 fdw137_t2) +(26 rows) + +SELECT q.b, count(fdw137_t1.c1), sum(q.a) FROM fdw137_t1 left join (SELECT min(13), avg(fdw137_t1.c1), sum(fdw137_t2.c1) FROM fdw137_t1 right join fdw137_t2 ON (fdw137_t1.c8 = fdw137_t2.c1) WHERE fdw137_t1.c8 = 20) q(a, b, c) ON (fdw137_t1.c8 = q.b) WHERE fdw137_t1.c1 between 100 and 500 GROUP BY q.b ORDER BY 1 nulls last, 2; + b | count | sum +---+-------+----- + | 5 | +(1 row) + +-- Not supported cases +-- The COUNT of column +EXPLAIN (VERBOSE, COSTS OFF) +SELECT count(c8) FROM fdw137_t1 ; + QUERY PLAN +-------------------------------------------------------- + Aggregate + Output: count(c8) + -> Foreign Scan on public.fdw137_t1 + Output: _id, c1, c2, c3, c4, c5, c6, c7, c8 + Foreign Namespace: mongo_fdw_regress.test_tbl1 +(5 rows) + +SELECT count(c8) FROM fdw137_t1 ; + count +------- + 15 +(1 row) + +-- Grouping sets +EXPLAIN (VERBOSE, COSTS OFF) +SELECT c8, sum(c1) FROM fdw137_t1 WHERE c8 > 10 GROUP BY rollup(c8) ORDER BY 1 nulls last; + QUERY PLAN +-------------------------------------------------------------- + Sort + Output: c8, (sum(c1)) + Sort Key: fdw137_t1.c8 + -> MixedAggregate + Output: c8, sum(c1) + Hash Key: fdw137_t1.c8 + Group Key: () + -> Foreign Scan on public.fdw137_t1 + Output: _id, c1, c2, c3, c4, c5, c6, c7, c8 + Foreign Namespace: mongo_fdw_regress.test_tbl1 +(10 rows) + +SELECT c8, sum(c1) FROM fdw137_t1 WHERE c8 > 10 GROUP BY rollup(c8) ORDER BY 1 nulls last; + c8 | sum +----+------ + 20 | 3700 + 30 | 3800 + 60 | 1500 + | 9000 +(4 rows) + +EXPLAIN (VERBOSE, COSTS OFF) +SELECT c8, sum(c1) FROM fdw137_t1 WHERE c8 > 3 GROUP BY cube(c8) ORDER BY 1 nulls last; + QUERY PLAN +-------------------------------------------------------------- + Sort + Output: c8, (sum(c1)) + Sort Key: fdw137_t1.c8 + -> MixedAggregate + Output: c8, sum(c1) + Hash Key: fdw137_t1.c8 + Group Key: () + -> Foreign Scan on public.fdw137_t1 + Output: _id, c1, c2, c3, c4, c5, c6, c7, c8 + Foreign Namespace: mongo_fdw_regress.test_tbl1 +(10 rows) + +SELECT c8, sum(c1) FROM fdw137_t1 WHERE c8 > 3 GROUP BY cube(c8) ORDER BY 1 nulls last; + c8 | sum +----+------- + 10 | 3000 + 20 | 3700 + 30 | 3800 + 60 | 1500 + | 12000 +(5 rows) + +EXPLAIN (VERBOSE, COSTS OFF) +SELECT c8, c4, sum(c1) FROM fdw137_t1 WHERE c8 > 20 GROUP BY grouping sets(c8, c4) ORDER BY 1 nulls last, 2 nulls last; + QUERY PLAN +-------------------------------------------------------------- + Sort + Output: c8, c4, (sum(c1)) + Sort Key: fdw137_t1.c8, fdw137_t1.c4 + -> HashAggregate + Output: c8, c4, sum(c1) + Hash Key: fdw137_t1.c8 + Hash Key: fdw137_t1.c4 + -> Foreign Scan on public.fdw137_t1 + Output: _id, c1, c2, c3, c4, c5, c6, c7, c8 + Foreign Namespace: mongo_fdw_regress.test_tbl1 +(10 rows) + +SELECT c8, c4, sum(c1) FROM fdw137_t1 WHERE c8 > 20 GROUP BY grouping sets(c8, c4) ORDER BY 1 nulls last, 2 nulls last; + c8 | c4 | sum +----+------+------ + 30 | | 3800 + 60 | | 1500 + | 600 | 3200 + | 900 | 600 + | 1300 | 1500 +(5 rows) + +EXPLAIN (VERBOSE, COSTS OFF) +SELECT c8, sum(c1), grouping(c8) FROM fdw137_t1 WHERE c8 > 10 GROUP BY c8 ORDER BY 1 nulls last; + QUERY PLAN +-------------------------------------------------------------- + Sort + Output: c8, (sum(c1)), (GROUPING(c8)) + Sort Key: fdw137_t1.c8 + -> HashAggregate + Output: c8, sum(c1), GROUPING(c8) + Group Key: fdw137_t1.c8 + -> Foreign Scan on public.fdw137_t1 + Output: _id, c1, c2, c3, c4, c5, c6, c7, c8 + Foreign Namespace: mongo_fdw_regress.test_tbl1 +(9 rows) + +SELECT c8, sum(c1), grouping(c8) FROM fdw137_t1 WHERE c8 > 10 GROUP BY c8 ORDER BY 1 nulls last; + c8 | sum | grouping +----+------+---------- + 20 | 3700 | 0 + 30 | 3800 | 0 + 60 | 1500 | 0 +(3 rows) + +-- DISTINCT itself is not pushed down, whereas underneath aggregate is pushed +EXPLAIN (VERBOSE, COSTS OFF) +SELECT DISTINCT sum(c1) s FROM fdw137_t1 WHERE c1 > 1000 GROUP BY c1 ORDER BY 1; + QUERY PLAN +--------------------------------------------------------------------------------------- + Unique + Output: (sum(c1)), c1 + -> Sort + Output: (sum(c1)), c1 + Sort Key: (sum(fdw137_t1.c1)) + -> Foreign Scan + Output: (sum(c1)), c1 + Foreign Namespace: Aggregate on (mongo_fdw_regress.test_tbl1 fdw137_t1) +(8 rows) + +SELECT DISTINCT sum(c1) s FROM fdw137_t1 WHERE c1 > 1000 GROUP BY c1 ORDER BY 1; + s +------ + 1100 + 1200 + 1300 + 1400 + 1500 + 1600 +(6 rows) + +-- WindowAgg +EXPLAIN (VERBOSE, COSTS OFF) +SELECT c8, sum(c8), count(c8) over (partition by c8%2) FROM fdw137_t1 WHERE c8 > 10 GROUP BY c8 ORDER BY 1; + QUERY PLAN +--------------------------------------------------------------------------------------------- + Sort + Output: c8, (sum(c8)), (count(c8) OVER (?)), ((c8 % 2)) + Sort Key: fdw137_t1.c8 + -> WindowAgg + Output: c8, (sum(c8)), count(c8) OVER (?), ((c8 % 2)) + -> Sort + Output: c8, ((c8 % 2)), (sum(c8)) + Sort Key: ((fdw137_t1.c8 % 2)) + -> Foreign Scan + Output: c8, (c8 % 2), (sum(c8)) + Foreign Namespace: Aggregate on (mongo_fdw_regress.test_tbl1 fdw137_t1) +(11 rows) + +SELECT c8, sum(c8), count(c8) over (partition by c8%2) FROM fdw137_t1 WHERE c8 > 10 GROUP BY c8 ORDER BY 1; + c8 | sum | count +----+-----+------- + 20 | 100 | 3 + 30 | 180 | 3 + 60 | 60 | 3 +(3 rows) + +EXPLAIN (VERBOSE, COSTS OFF) +SELECT c8, array_agg(c8) over (partition by c8%2 ORDER BY c8 desc) FROM fdw137_t1 WHERE c8 > 10 GROUP BY c8 ORDER BY 1; + QUERY PLAN +--------------------------------------------------------------------------------------------- + Sort + Output: c8, (array_agg(c8) OVER (?)), ((c8 % 2)) + Sort Key: fdw137_t1.c8 + -> WindowAgg + Output: c8, array_agg(c8) OVER (?), ((c8 % 2)) + -> Sort + Output: c8, ((c8 % 2)) + Sort Key: ((fdw137_t1.c8 % 2)), fdw137_t1.c8 DESC + -> Foreign Scan + Output: c8, (c8 % 2) + Foreign Namespace: Aggregate on (mongo_fdw_regress.test_tbl1 fdw137_t1) +(11 rows) + +SELECT c8, array_agg(c8) over (partition by c8%2 ORDER BY c8 desc) FROM fdw137_t1 WHERE c8 > 10 GROUP BY c8 ORDER BY 1; + c8 | array_agg +----+------------ + 20 | {60,30,20} + 30 | {60,30} + 60 | {60} +(3 rows) + +EXPLAIN (VERBOSE, COSTS OFF) +SELECT c8, array_agg(c8) over (partition by c8%2 ORDER BY c8 range between current row and unbounded following) FROM fdw137_t1 WHERE c8 > 10 GROUP BY c8 ORDER BY 1; + QUERY PLAN +--------------------------------------------------------------------------------------------- + Sort + Output: c8, (array_agg(c8) OVER (?)), ((c8 % 2)) + Sort Key: fdw137_t1.c8 + -> WindowAgg + Output: c8, array_agg(c8) OVER (?), ((c8 % 2)) + -> Sort + Output: c8, ((c8 % 2)) + Sort Key: ((fdw137_t1.c8 % 2)), fdw137_t1.c8 + -> Foreign Scan + Output: c8, (c8 % 2) + Foreign Namespace: Aggregate on (mongo_fdw_regress.test_tbl1 fdw137_t1) +(11 rows) + +SELECT c8, array_agg(c8) over (partition by c8%2 ORDER BY c8 range between current row and unbounded following) FROM fdw137_t1 WHERE c8 > 10 GROUP BY c8 ORDER BY 1; + c8 | array_agg +----+------------ + 20 | {20,30,60} + 30 | {30,60} + 60 | {60} +(3 rows) + +-- User defined function for user defined aggregate, VARIADIC +CREATE FUNCTION least_accum(anyelement, variadic anyarray) +returns anyelement language sql AS + 'SELECT least($1, min($2[i])) FROM generate_subscripts($2,2) g(i)'; +CREATE aggregate least_agg(variadic items anyarray) ( + stype = anyelement, sfunc = least_accum +); +-- Not pushed down due to user defined aggregate +EXPLAIN (VERBOSE, COSTS OFF) +SELECT c2, least_agg(c1) FROM fdw137_t1 GROUP BY c2 ORDER BY c2; + QUERY PLAN +-------------------------------------------------------------- + Sort + Output: c2, (least_agg(VARIADIC ARRAY[c1])) + Sort Key: fdw137_t1.c2 + -> HashAggregate + Output: c2, least_agg(VARIADIC ARRAY[c1]) + Group Key: fdw137_t1.c2 + -> Foreign Scan on public.fdw137_t1 + Output: _id, c1, c2, c3, c4, c5, c6, c7, c8 + Foreign Namespace: mongo_fdw_regress.test_tbl1 +(9 rows) + +SELECT c2, least_agg(c1) FROM fdw137_t1 GROUP BY c2 ORDER BY c2; + c2 | least_agg +-------+----------- + EMP1 | + EMP10 | + EMP11 | + EMP12 | + EMP13 | + EMP14 | + EMP15 | + EMP16 | + EMP2 | + EMP3 | + EMP4 | + EMP5 | + EMP6 | + EMP7 | + EMP8 | + EMP9 | +(16 rows) + +-- Test partition-wise aggregate +SET enable_partitionwise_aggregate TO ON; +-- Create the partition tables +CREATE TABLE fprt1 (_id NAME, c1 INTEGER, c2 INTEGER, c3 TEXT) PARTITION BY RANGE(c1); +CREATE FOREIGN TABLE ftprt1_p1 PARTITION OF fprt1 FOR VALUES FROM (1) TO (4) + SERVER mongo_server OPTIONS (database 'mongo_fdw_regress', collection 'test1'); +CREATE FOREIGN TABLE ftprt1_p2 PARTITION OF fprt1 FOR VALUES FROM (5) TO (8) + SERVER mongo_server OPTIONS (database 'mongo_fdw_regress', collection 'test2'); +-- Plan with partitionwise aggregates is enabled +EXPLAIN (VERBOSE, COSTS OFF) +SELECT c1, sum(c1) FROM fprt1 GROUP BY c1 ORDER BY 2; + QUERY PLAN +------------------------------------------------------------------------------- + Sort + Output: fprt1.c1, (sum(fprt1.c1)) + Sort Key: (sum(fprt1.c1)) + -> Append + -> Foreign Scan + Output: fprt1.c1, (sum(fprt1.c1)) + Foreign Namespace: Aggregate on (mongo_fdw_regress.test1 fprt1) + -> Foreign Scan + Output: fprt1_1.c1, (sum(fprt1_1.c1)) + Foreign Namespace: Aggregate on (mongo_fdw_regress.test2 fprt1) +(10 rows) + +SELECT c1, sum(c1) FROM fprt1 GROUP BY c1 ORDER BY 2; + c1 | sum +----+----- + 1 | 1 + 2 | 2 + 3 | 3 + 4 | 4 + 5 | 5 + 6 | 6 + 7 | 7 + 8 | 8 +(8 rows) + +EXPLAIN (VERBOSE, COSTS OFF) +SELECT c1, sum(c2), min(c2), count(*) FROM fprt1 GROUP BY c1 HAVING avg(c2) < 22 ORDER BY 2; + QUERY PLAN +------------------------------------------------------------------------------------ + Sort + Output: fprt1.c1, (sum(fprt1.c2)), (min(fprt1.c2)), (count(*)) + Sort Key: (sum(fprt1.c2)) + -> Append + -> Foreign Scan + Output: fprt1.c1, (sum(fprt1.c2)), (min(fprt1.c2)), (count(*)) + Foreign Namespace: Aggregate on (mongo_fdw_regress.test1 fprt1) + -> Foreign Scan + Output: fprt1_1.c1, (sum(fprt1_1.c2)), (min(fprt1_1.c2)), (count(*)) + Foreign Namespace: Aggregate on (mongo_fdw_regress.test2 fprt1) +(10 rows) + +SELECT c1, sum(c2), min(c2), count(*) FROM fprt1 GROUP BY c1 HAVING avg(c2) < 22 ORDER BY 2; + c1 | sum | min | count +----+-----+-----+------- + 1 | 1 | 1 | 1 + 2 | 2 | 2 | 1 + 3 | 3 | 3 | 1 + 4 | 4 | 4 | 1 + 5 | 5 | 5 | 1 + 6 | 6 | 6 | 1 + 7 | 7 | 7 | 1 + 8 | 8 | 8 | 1 +(8 rows) + +-- Check with whole-row reference +-- Should have all the columns in the target list for the given relation +EXPLAIN (VERBOSE, COSTS OFF) +SELECT c1, count(t1) FROM fprt1 t1 GROUP BY c1 HAVING avg(c2) < 22 ORDER BY 1; + QUERY PLAN +---------------------------------------------------------------- + Sort + Output: t1.c1, (count(((t1.*)::fprt1))) + Sort Key: t1.c1 + -> Append + -> HashAggregate + Output: t1.c1, count(((t1.*)::fprt1)) + Group Key: t1.c1 + Filter: (avg(t1.c2) < '22'::numeric) + -> Foreign Scan on public.ftprt1_p1 t1 + Output: t1.c1, t1.*, t1.c2 + Foreign Namespace: mongo_fdw_regress.test1 + -> HashAggregate + Output: t1_1.c1, count(((t1_1.*)::fprt1)) + Group Key: t1_1.c1 + Filter: (avg(t1_1.c2) < '22'::numeric) + -> Foreign Scan on public.ftprt1_p2 t1_1 + Output: t1_1.c1, t1_1.*, t1_1.c2 + Foreign Namespace: mongo_fdw_regress.test2 +(18 rows) + +SELECT c1, count(t1) FROM fprt1 t1 GROUP BY c1 HAVING avg(c2) < 22 ORDER BY 1; + c1 | count +----+------- + 1 | 1 + 2 | 1 + 3 | 1 + 4 | 1 + 5 | 1 + 6 | 1 + 7 | 1 + 8 | 1 +(8 rows) + +SET enable_partitionwise_aggregate TO OFF; +-- Support enable_aggregate_pushdown option at server level and table level. +-- Check only boolean values are accepted. +ALTER SERVER mongo_server OPTIONS (ADD enable_aggregate_pushdown 'non-bolean'); +ERROR: enable_aggregate_pushdown requires a Boolean value +-- Test the option at server level. +ALTER SERVER mongo_server OPTIONS (ADD enable_aggregate_pushdown 'false'); +EXPLAIN (VERBOSE, COSTS OFF) +SELECT count(*) FROM fdw137_t1 GROUP BY c1 HAVING min(c1) > 500 ORDER BY 1; + QUERY PLAN +-------------------------------------------------------------- + Sort + Output: (count(*)), c1 + Sort Key: (count(*)) + -> HashAggregate + Output: count(*), c1 + Group Key: fdw137_t1.c1 + Filter: (min(fdw137_t1.c1) > 500) + -> Foreign Scan on public.fdw137_t1 + Output: _id, c1, c2, c3, c4, c5, c6, c7, c8 + Foreign Namespace: mongo_fdw_regress.test_tbl1 +(10 rows) + +ALTER SERVER mongo_server OPTIONS (SET enable_aggregate_pushdown 'true'); +EXPLAIN (VERBOSE, COSTS OFF) +SELECT count(*) FROM fdw137_t1 GROUP BY c1 HAVING min(c1) > 500 ORDER BY 1; + QUERY PLAN +--------------------------------------------------------------------------------- + Sort + Output: (count(*)), c1 + Sort Key: (count(*)) + -> Foreign Scan + Output: (count(*)), c1 + Foreign Namespace: Aggregate on (mongo_fdw_regress.test_tbl1 fdw137_t1) +(6 rows) + +-- Test the option at table level. Setting option at table level does not +-- affect the setting at server level. +ALTER FOREIGN TABLE fdw137_t1 OPTIONS (ADD enable_aggregate_pushdown 'false'); +EXPLAIN (VERBOSE, COSTS OFF) +SELECT count(*) FROM fdw137_t1 GROUP BY c1 HAVING min(c1) > 500 ORDER BY 1; + QUERY PLAN +-------------------------------------------------------------- + Sort + Output: (count(*)), c1 + Sort Key: (count(*)) + -> HashAggregate + Output: count(*), c1 + Group Key: fdw137_t1.c1 + Filter: (min(fdw137_t1.c1) > 500) + -> Foreign Scan on public.fdw137_t1 + Output: _id, c1, c2, c3, c4, c5, c6, c7, c8 + Foreign Namespace: mongo_fdw_regress.test_tbl1 +(10 rows) + +ALTER SERVER mongo_server OPTIONS (SET enable_aggregate_pushdown 'false'); +ALTER FOREIGN TABLE fdw137_t1 OPTIONS (SET enable_aggregate_pushdown 'true'); +EXPLAIN (VERBOSE, COSTS OFF) +SELECT count(*) FROM fdw137_t1 GROUP BY c1 HAVING min(c1) > 500 ORDER BY 1; + QUERY PLAN +--------------------------------------------------------------------------------- + Sort + Output: (count(*)), c1 + Sort Key: (count(*)) + -> Foreign Scan + Output: (count(*)), c1 + Foreign Namespace: Aggregate on (mongo_fdw_regress.test_tbl1 fdw137_t1) +(6 rows) + +-- Test option for aggregation over join. Allow aggregation only if enabled for +-- both the relations involved in the join. +ALTER SERVER mongo_server OPTIONS (SET enable_aggregate_pushdown 'true'); +ALTER FOREIGN TABLE fdw137_t1 OPTIONS (SET enable_aggregate_pushdown 'false'); +ALTER FOREIGN TABLE fdw137_t2 OPTIONS (ADD enable_aggregate_pushdown 'false'); +EXPLAIN (VERBOSE, COSTS OFF) +SELECT sum(t2.c1), t1.c8 FROM fdw137_t1 t1 LEFT JOIN fdw137_t2 t2 ON (t1.c8 = t2.c1) GROUP BY t1.c8 ORDER BY 2; + QUERY PLAN +-------------------------------------------------------------------------------------------------------------- + Sort + Output: (sum(t2.c1)), t1.c8 + Sort Key: t1.c8 + -> HashAggregate + Output: sum(t2.c1), t1.c8 + Group Key: t1.c8 + -> Foreign Scan + Output: t1.c8, t2.c1 + Foreign Namespace: (mongo_fdw_regress.test_tbl1 t1) LEFT JOIN (mongo_fdw_regress.test_tbl2 t2) +(9 rows) + +ALTER SERVER mongo_server OPTIONS (SET enable_aggregate_pushdown 'true'); +ALTER FOREIGN TABLE fdw137_t1 OPTIONS (SET enable_aggregate_pushdown 'true'); +ALTER FOREIGN TABLE fdw137_t2 OPTIONS (SET enable_aggregate_pushdown 'false'); +EXPLAIN (VERBOSE, COSTS OFF) +SELECT sum(t2.c1), t1.c8 FROM fdw137_t1 t1 LEFT JOIN fdw137_t2 t2 ON (t1.c8 = t2.c1) GROUP BY t1.c8 ORDER BY 2; + QUERY PLAN +-------------------------------------------------------------------------------------------------------------- + Sort + Output: (sum(t2.c1)), t1.c8 + Sort Key: t1.c8 + -> HashAggregate + Output: sum(t2.c1), t1.c8 + Group Key: t1.c8 + -> Foreign Scan + Output: t1.c8, t2.c1 + Foreign Namespace: (mongo_fdw_regress.test_tbl1 t1) LEFT JOIN (mongo_fdw_regress.test_tbl2 t2) +(9 rows) + +ALTER SERVER mongo_server OPTIONS (SET enable_aggregate_pushdown 'false'); +ALTER FOREIGN TABLE fdw137_t1 OPTIONS (SET enable_aggregate_pushdown 'true'); +ALTER FOREIGN TABLE fdw137_t2 OPTIONS (SET enable_aggregate_pushdown 'true'); +EXPLAIN (VERBOSE, COSTS OFF) +SELECT sum(t2.c1), t1.c8 FROM fdw137_t1 t1 LEFT JOIN fdw137_t2 t2 ON (t1.c8 = t2.c1) GROUP BY t1.c8 ORDER BY 2 ASC NULLS FIRST; + QUERY PLAN +----------------------------------------------------------------------------------------------------------------- + Foreign Scan + Output: (sum(t2.c1)), t1.c8 + Foreign Namespace: Aggregate on ((mongo_fdw_regress.test_tbl1 t1) LEFT JOIN (mongo_fdw_regress.test_tbl2 t2)) +(3 rows) + +-- FDW-560: Aggregation over nested join. As nested join push down is not +-- supported, aggregation shouldn't get pushdown. +EXPLAIN (VERBOSE, COSTS OFF) +SELECT sum(t2.c1), t1.c8 FROM fdw137_t1 t1 LEFT JOIN fdw137_t2 t2 ON (t1.c8 = t2.c1) INNER JOIN fdw137_t1 t3 ON (t3.c1 = t1.c1) GROUP BY t1.c8 ORDER BY 2; + QUERY PLAN +--------------------------------------------------------------------------------------------------------------------- + GroupAggregate + Output: sum(t2.c1), t1.c8 + Group Key: t1.c8 + -> Merge Left Join + Output: t1.c8, t2.c1 + Merge Cond: (t1.c8 = t2.c1) + -> Sort + Output: t1.c8 + Sort Key: t1.c8 + -> Foreign Scan + Output: t1.c8 + Foreign Namespace: (mongo_fdw_regress.test_tbl1 t1) INNER JOIN (mongo_fdw_regress.test_tbl1 t3) + -> Sort + Output: t2.c1 + Sort Key: t2.c1 + -> Foreign Scan on public.fdw137_t2 t2 + Output: t2.c1 + Foreign Namespace: mongo_fdw_regress.test_tbl2 +(18 rows) + +SELECT sum(t2.c1), t1.c8 FROM fdw137_t1 t1 LEFT JOIN fdw137_t2 t2 ON (t1.c8 = t2.c1) INNER JOIN fdw137_t1 t3 ON (t3.c1 = t1.c1) GROUP BY t1.c8 ORDER BY 2; + sum | c8 +-----+---- + 30 | 10 + 100 | 20 + 180 | 30 + | 60 + | +(5 rows) + +-- Check when enable_join_pushdown is OFF and enable_aggregate_pushdown is ON. +-- Shouldn't push down join as well as aggregation. +ALTER SERVER mongo_server OPTIONS (ADD enable_join_pushdown 'false'); +ALTER SERVER mongo_server OPTIONS (SET enable_aggregate_pushdown 'true'); +EXPLAIN (VERBOSE, COSTS OFF) +SELECT sum(t2.c1), t1.c8 FROM fdw137_t1 t1 LEFT JOIN fdw137_t2 t2 ON (t1.c8 = t2.c1) GROUP BY t1.c8 ORDER BY 2; + QUERY PLAN +-------------------------------------------------------------------- + GroupAggregate + Output: sum(t2.c1), t1.c8 + Group Key: t1.c8 + -> Merge Left Join + Output: t1.c8, t2.c1 + Merge Cond: (t1.c8 = t2.c1) + -> Sort + Output: t1.c8 + Sort Key: t1.c8 + -> Foreign Scan on public.fdw137_t1 t1 + Output: t1.c8 + Foreign Namespace: mongo_fdw_regress.test_tbl1 + -> Sort + Output: t2.c1 + Sort Key: t2.c1 + -> Foreign Scan on public.fdw137_t2 t2 + Output: t2.c1 + Foreign Namespace: mongo_fdw_regress.test_tbl2 +(18 rows) + +-- FDW-134: Test with number of columns more than 32 +CREATE FOREIGN TABLE f_test_large (_id int, + a01 int, a02 int, a03 int, a04 int, a05 int, a06 int, a07 int, a08 int, a09 int, a10 int, + a11 int, a12 int, a13 int, a14 int, a15 int, a16 int, a17 int, a18 int, a19 int, a20 int, + a21 int, a22 int, a23 int, a24 int, a25 int, a26 int, a27 int, a28 int, a29 int, a30 int, + a31 int, a32 int, a33 int, a34 int, a35 int) + SERVER mongo_server OPTIONS (database 'mongo_fdw_regress', collection 'mongo_test_large'); +-- Shouldn't pushdown ORDERBY clause due to exceeded number of path keys limit. +EXPLAIN (VERBOSE, COSTS FALSE) +SELECT a32, sum(a32) FROM f_test_large GROUP BY + a01, a02, a03, a04, a05, a06, a07, a08, a09, a10, a11, a12, a13, a14, a15, + a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, + a31, a32, a33, a34, a35 ORDER BY + a01 ASC NULLS FIRST, a02 ASC NULLS FIRST, a03 ASC NULLS FIRST, a04 ASC NULLS FIRST, a05 ASC NULLS FIRST, + a06 ASC NULLS FIRST, a07 ASC NULLS FIRST, a08 ASC NULLS FIRST, a09 ASC NULLS FIRST, a10 ASC NULLS FIRST, + a11 ASC NULLS FIRST, a12 ASC NULLS FIRST, a13 ASC NULLS FIRST, a14 ASC NULLS FIRST, a15 ASC NULLS FIRST, + a16 ASC NULLS FIRST, a17 ASC NULLS FIRST, a18 ASC NULLS FIRST, a19 ASC NULLS FIRST, a20 ASC NULLS FIRST, + a21 ASC NULLS FIRST, a22 ASC NULLS FIRST, a23 ASC NULLS FIRST, a24 ASC NULLS FIRST, a25 ASC NULLS FIRST, + a26 ASC NULLS FIRST, a27 ASC NULLS FIRST, a28 ASC NULLS FIRST, a29 ASC NULLS FIRST, a30 ASC NULLS FIRST, + a31 ASC NULLS FIRST, a32 ASC NULLS FIRST, a33 ASC NULLS FIRST, a34 DESC NULLS LAST, a35 ASC NULLS FIRST; + QUERY PLAN +---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Sort + Output: a32, (sum(a32)), a01, a02, a03, a04, a05, a06, a07, a08, a09, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, a31, a33, a34, a35 + Sort Key: f_test_large.a01 NULLS FIRST, f_test_large.a02 NULLS FIRST, f_test_large.a03 NULLS FIRST, f_test_large.a04 NULLS FIRST, f_test_large.a05 NULLS FIRST, f_test_large.a06 NULLS FIRST, f_test_large.a07 NULLS FIRST, f_test_large.a08 NULLS FIRST, f_test_large.a09 NULLS FIRST, f_test_large.a10 NULLS FIRST, f_test_large.a11 NULLS FIRST, f_test_large.a12 NULLS FIRST, f_test_large.a13 NULLS FIRST, f_test_large.a14 NULLS FIRST, f_test_large.a15 NULLS FIRST, f_test_large.a16 NULLS FIRST, f_test_large.a17 NULLS FIRST, f_test_large.a18 NULLS FIRST, f_test_large.a19 NULLS FIRST, f_test_large.a20 NULLS FIRST, f_test_large.a21 NULLS FIRST, f_test_large.a22 NULLS FIRST, f_test_large.a23 NULLS FIRST, f_test_large.a24 NULLS FIRST, f_test_large.a25 NULLS FIRST, f_test_large.a26 NULLS FIRST, f_test_large.a27 NULLS FIRST, f_test_large.a28 NULLS FIRST, f_test_large.a29 NULLS FIRST, f_test_large.a30 NULLS FIRST, f_test_large.a31 NULLS FIRST, f_test_large.a32 NULLS FIRST, f_test_large.a33 NULLS FIRST, f_test_large.a34 DESC NULLS LAST, f_test_large.a35 NULLS FIRST + -> Foreign Scan + Output: a32, (sum(a32)), a01, a02, a03, a04, a05, a06, a07, a08, a09, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, a31, a33, a34, a35 + Foreign Namespace: Aggregate on (mongo_fdw_regress.mongo_test_large f_test_large) +(6 rows) + +SELECT a32, sum(a32) FROM f_test_large GROUP BY + a01, a02, a03, a04, a05, a06, a07, a08, a09, a10, a11, a12, a13, a14, a15, + a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, + a31, a32, a33, a34, a35 ORDER BY + a01 ASC NULLS FIRST, a02 ASC NULLS FIRST, a03 ASC NULLS FIRST, a04 ASC NULLS FIRST, a05 ASC NULLS FIRST, + a06 ASC NULLS FIRST, a07 ASC NULLS FIRST, a08 ASC NULLS FIRST, a09 ASC NULLS FIRST, a10 ASC NULLS FIRST, + a11 ASC NULLS FIRST, a12 ASC NULLS FIRST, a13 ASC NULLS FIRST, a14 ASC NULLS FIRST, a15 ASC NULLS FIRST, + a16 ASC NULLS FIRST, a17 ASC NULLS FIRST, a18 ASC NULLS FIRST, a19 ASC NULLS FIRST, a20 ASC NULLS FIRST, + a21 ASC NULLS FIRST, a22 ASC NULLS FIRST, a23 ASC NULLS FIRST, a24 ASC NULLS FIRST, a25 ASC NULLS FIRST, + a26 ASC NULLS FIRST, a27 ASC NULLS FIRST, a28 ASC NULLS FIRST, a29 ASC NULLS FIRST, a30 ASC NULLS FIRST, + a31 ASC NULLS FIRST, a32 ASC NULLS FIRST, a33 ASC NULLS FIRST, a34 DESC NULLS LAST, a35 ASC NULLS FIRST; + a32 | sum +-----+----- + 2 | 2 + 32 | 32 + 32 | 32 + 32 | 32 + 132 | 132 +(5 rows) + +-- Should pushdown ORDERBY clause because number of path keys are in limit. +EXPLAIN (VERBOSE, COSTS FALSE) +SELECT a32, sum(a32) FROM f_test_large GROUP BY + a01, a02, a03, a04, a05, a06, a07, a08, a09, a10, a11, a12, a13, a14, a15, + a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, + a31, a32 ORDER BY + a01 ASC NULLS FIRST, a02 ASC NULLS FIRST, a03 ASC NULLS FIRST, a04 ASC NULLS FIRST, a05 ASC NULLS FIRST, + a06 ASC NULLS FIRST, a07 ASC NULLS FIRST, a08 ASC NULLS FIRST, a09 ASC NULLS FIRST, a10 ASC NULLS FIRST, + a11 ASC NULLS FIRST, a12 ASC NULLS FIRST, a13 ASC NULLS FIRST, a14 ASC NULLS FIRST, a15 ASC NULLS FIRST, + a16 ASC NULLS FIRST, a17 ASC NULLS FIRST, a18 ASC NULLS FIRST, a19 ASC NULLS FIRST, a20 ASC NULLS FIRST, + a21 ASC NULLS FIRST, a22 ASC NULLS FIRST, a23 ASC NULLS FIRST, a24 ASC NULLS FIRST, a25 ASC NULLS FIRST, + a26 ASC NULLS FIRST, a27 ASC NULLS FIRST, a28 ASC NULLS FIRST, a29 ASC NULLS FIRST, a30 ASC NULLS FIRST, + a31 ASC NULLS FIRST, a32 ASC NULLS FIRST; + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Foreign Scan + Output: a32, (sum(a32)), a01, a02, a03, a04, a05, a06, a07, a08, a09, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, a31 + Foreign Namespace: Aggregate on (mongo_fdw_regress.mongo_test_large f_test_large) +(3 rows) + +SELECT a32, sum(a32) FROM f_test_large GROUP BY + a01, a02, a03, a04, a05, a06, a07, a08, a09, a10, a11, a12, a13, a14, a15, + a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, + a31, a32 ORDER BY + a01 ASC NULLS FIRST, a02 ASC NULLS FIRST, a03 ASC NULLS FIRST, a04 ASC NULLS FIRST, a05 ASC NULLS FIRST, + a06 ASC NULLS FIRST, a07 ASC NULLS FIRST, a08 ASC NULLS FIRST, a09 ASC NULLS FIRST, a10 ASC NULLS FIRST, + a11 ASC NULLS FIRST, a12 ASC NULLS FIRST, a13 ASC NULLS FIRST, a14 ASC NULLS FIRST, a15 ASC NULLS FIRST, + a16 ASC NULLS FIRST, a17 ASC NULLS FIRST, a18 ASC NULLS FIRST, a19 ASC NULLS FIRST, a20 ASC NULLS FIRST, + a21 ASC NULLS FIRST, a22 ASC NULLS FIRST, a23 ASC NULLS FIRST, a24 ASC NULLS FIRST, a25 ASC NULLS FIRST, + a26 ASC NULLS FIRST, a27 ASC NULLS FIRST, a28 ASC NULLS FIRST, a29 ASC NULLS FIRST, a30 ASC NULLS FIRST, + a31 ASC NULLS FIRST, a32 ASC NULLS FIRST; + a32 | sum +-----+----- + 2 | 2 + 32 | 96 + 132 | 132 +(3 rows) + +-- FDW-131: Limit and offset pushdown with Aggregate pushdown. +SELECT avg(c1), c1 FROM fdw137_t2 GROUP BY c1 ORDER BY c1; + avg | c1 +-----+---- + 10 | 10 + 20 | 20 + 30 | 30 + 40 | 40 + 50 | 50 + | +(6 rows) + +EXPLAIN (VERBOSE, COSTS OFF) +SELECT sum(c1), c1 FROM fdw137_t2 GROUP BY c1 ORDER BY c1 ASC NULLS FIRST LIMIT 1 OFFSET 1; + QUERY PLAN +--------------------------------------------------------------------------- + Foreign Scan + Output: (sum(c1)), c1 + Foreign Namespace: Aggregate on (mongo_fdw_regress.test_tbl2 fdw137_t2) +(3 rows) + +SELECT sum(c1), c1 FROM fdw137_t2 GROUP BY c1 ORDER BY c1 ASC NULLS FIRST LIMIT 1 OFFSET 1; + sum | c1 +-----+---- + 10 | 10 +(1 row) + +-- Limit 0, Offset 0 with aggregates. +EXPLAIN (VERBOSE, COSTS OFF) +SELECT sum(c1), c1 FROM fdw137_t2 GROUP BY c1 ORDER BY c1 ASC NULLS FIRST LIMIT 0 OFFSET 0; + QUERY PLAN +--------------------------------------------------------------------------- + Foreign Scan + Output: (sum(c1)), c1 + Foreign Namespace: Aggregate on (mongo_fdw_regress.test_tbl2 fdw137_t2) +(3 rows) + +SELECT sum(c1), c1 FROM fdw137_t2 GROUP BY c1 ORDER BY c1 ASC NULLS FIRST LIMIT 0 OFFSET 0; + sum | c1 +-----+---- +(0 rows) + +-- Limit NULL +EXPLAIN (VERBOSE, COSTS OFF) +SELECT sum(c1), c1 FROM fdw137_t2 GROUP BY c1 ORDER BY c1 ASC NULLS FIRST LIMIT NULL OFFSET 2; + QUERY PLAN +--------------------------------------------------------------------------- + Foreign Scan + Output: (sum(c1)), c1 + Foreign Namespace: Aggregate on (mongo_fdw_regress.test_tbl2 fdw137_t2) +(3 rows) + +SELECT sum(c1), c1 FROM fdw137_t2 GROUP BY c1 ORDER BY c1 ASC NULLS FIRST LIMIT NULL OFFSET 2; + sum | c1 +-----+---- + 20 | 20 + 30 | 30 + 40 | 40 + 50 | 50 +(4 rows) + +-- Limit ALL +EXPLAIN (VERBOSE, COSTS OFF) +SELECT sum(c1), c1 FROM fdw137_t2 GROUP BY c1 ORDER BY c1 ASC NULLS FIRST LIMIT ALL OFFSET 2; + QUERY PLAN +--------------------------------------------------------------------------- + Foreign Scan + Output: (sum(c1)), c1 + Foreign Namespace: Aggregate on (mongo_fdw_regress.test_tbl2 fdw137_t2) +(3 rows) + +SELECT sum(c1), c1 FROM fdw137_t2 GROUP BY c1 ORDER BY c1 ASC NULLS FIRST LIMIT ALL OFFSET 2; + sum | c1 +-----+---- + 20 | 20 + 30 | 30 + 40 | 40 + 50 | 50 +(4 rows) + +-- Limit with -ve value. Shouldn't pushdown. +EXPLAIN (VERBOSE, COSTS FALSE) +SELECT c1, sum(c1) FROM fdw137_t2 GROUP BY c1 ORDER BY 1 ASC NULLS FIRST LIMIT -1; + QUERY PLAN +--------------------------------------------------------------------------------- + Limit + Output: c1, (sum(c1)) + -> Foreign Scan + Output: c1, (sum(c1)) + Foreign Namespace: Aggregate on (mongo_fdw_regress.test_tbl2 fdw137_t2) +(5 rows) + +-- Should throw an error. +SELECT c1, sum(c1) FROM fdw137_t2 GROUP BY c1 ORDER BY 1 ASC NULLS FIRST LIMIT -1; +ERROR: LIMIT must not be negative +-- Offset with -ve value. Shouldn't pushdown. +EXPLAIN (VERBOSE, COSTS FALSE) +SELECT c1, sum(c1) FROM fdw137_t2 GROUP BY c1 ORDER BY 1 ASC NULLS FIRST OFFSET -2; + QUERY PLAN +--------------------------------------------------------------------------------- + Limit + Output: c1, (sum(c1)) + -> Foreign Scan + Output: c1, (sum(c1)) + Foreign Namespace: Aggregate on (mongo_fdw_regress.test_tbl2 fdw137_t2) +(5 rows) + +-- Should throw an error. +SELECT c1, sum(c1) FROM fdw137_t2 GROUP BY c1 ORDER BY 1 ASC NULLS FIRST OFFSET -2; +ERROR: OFFSET must not be negative +-- Limit/Offset with -ve value. Shouldn't pushdown. +EXPLAIN (VERBOSE, COSTS FALSE) +SELECT c1, avg(c1) FROM fdw137_t2 GROUP BY c1 ORDER BY c1 ASC NULLS FIRST LIMIT -1 OFFSET -2; + QUERY PLAN +--------------------------------------------------------------------------------- + Limit + Output: c1, (avg(c1)) + -> Foreign Scan + Output: c1, (avg(c1)) + Foreign Namespace: Aggregate on (mongo_fdw_regress.test_tbl2 fdw137_t2) +(5 rows) + +-- Should throw an error. +SELECT c1, avg(c1) FROM fdw137_t2 GROUP BY c1 ORDER BY c1 ASC NULLS FIRST LIMIT -1 OFFSET -2; +ERROR: OFFSET must not be negative +-- Limit with expression evaluating to -ve value. +EXPLAIN (VERBOSE, COSTS FALSE) +SELECT c1, avg(c1) FROM fdw137_t2 GROUP BY c1 ORDER BY c1 ASC NULLS FIRST LIMIT (1 - (SELECT COUNT(*) FROM fdw137_t2)); + QUERY PLAN +----------------------------------------------------------------------------------- + Limit + Output: fdw137_t2.c1, (avg(fdw137_t2.c1)) + InitPlan 1 + -> Foreign Scan + Output: (count(*)) + Foreign Namespace: Aggregate on (mongo_fdw_regress.test_tbl2 fdw137_t2) + -> Foreign Scan + Output: fdw137_t2.c1, (avg(fdw137_t2.c1)) + Foreign Namespace: Aggregate on (mongo_fdw_regress.test_tbl2 fdw137_t2) +(9 rows) + +SELECT c1, avg(c1) FROM fdw137_t2 GROUP BY c1 ORDER BY c1 ASC NULLS FIRST LIMIT (1 - (SELECT COUNT(*) FROM fdw137_t2)); +ERROR: LIMIT must not be negative +-- FDW-559: Test mongo_fdw.enable_aggregate_pushdown GUC. +-- Check default value. Should be ON. +SHOW mongo_fdw.enable_aggregate_pushdown; + mongo_fdw.enable_aggregate_pushdown +------------------------------------- + on +(1 row) + +-- Negative testing for GUC value. +SET mongo_fdw.enable_aggregate_pushdown to 'abc'; +ERROR: parameter "mongo_fdw.enable_aggregate_pushdown" requires a Boolean value +--Disable the GUC enable_aggregate_pushdown. +SET mongo_fdw.enable_aggregate_pushdown to false; +ALTER SERVER mongo_server OPTIONS (SET enable_aggregate_pushdown 'true'); +ALTER FOREIGN TABLE fdw137_t1 OPTIONS (SET enable_aggregate_pushdown 'true'); +-- Shouldn't pushdown aggregate because GUC is OFF. +EXPLAIN (VERBOSE, COSTS FALSE) +SELECT count(*) FROM fdw137_t1 GROUP BY c1 HAVING min(c1) > 500 ORDER BY 1; + QUERY PLAN +-------------------------------------------------------------- + Sort + Output: (count(*)), c1 + Sort Key: (count(*)) + -> HashAggregate + Output: count(*), c1 + Group Key: fdw137_t1.c1 + Filter: (min(fdw137_t1.c1) > 500) + -> Foreign Scan on public.fdw137_t1 + Output: _id, c1, c2, c3, c4, c5, c6, c7, c8 + Foreign Namespace: mongo_fdw_regress.test_tbl1 +(10 rows) + +SELECT count(*) FROM fdw137_t1 GROUP BY c1 HAVING min(c1) > 500 ORDER BY 1; + count +------- + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 +(11 rows) + +--Enable the GUC enable_aggregate_pushdown. +SET mongo_fdw.enable_aggregate_pushdown to on; +ALTER SERVER mongo_server OPTIONS (SET enable_aggregate_pushdown 'true'); +ALTER FOREIGN TABLE fdw137_t1 OPTIONS (SET enable_aggregate_pushdown 'true'); +-- Should pushdown aggregate because GUC is ON. +EXPLAIN (VERBOSE, COSTS FALSE) +SELECT count(*) FROM fdw137_t1 GROUP BY c1 HAVING min(c1) > 500 ORDER BY 1; + QUERY PLAN +--------------------------------------------------------------------------------- + Sort + Output: (count(*)), c1 + Sort Key: (count(*)) + -> Foreign Scan + Output: (count(*)), c1 + Foreign Namespace: Aggregate on (mongo_fdw_regress.test_tbl1 fdw137_t1) +(6 rows) + +SELECT count(*) FROM fdw137_t1 GROUP BY c1 HAVING min(c1) > 500 ORDER BY 1; + count +------- + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 +(11 rows) + +-- Test for aggregation over join when server and table options for both the +-- tables is true and guc is enabled. Should pushdown. +SET mongo_fdw.enable_aggregate_pushdown to on; +SET mongo_fdw.enable_join_pushdown to on; +ALTER SERVER mongo_server OPTIONS (SET enable_join_pushdown 'true'); +ALTER FOREIGN TABLE fdw137_t1 OPTIONS (SET enable_aggregate_pushdown 'true'); +ALTER FOREIGN TABLE fdw137_t2 OPTIONS (SET enable_aggregate_pushdown 'true'); +EXPLAIN (VERBOSE, COSTS OFF) +SELECT count(*), t1.c8 FROM fdw137_t1 t1 LEFT JOIN fdw137_t2 t2 ON (t1.c8 = t2.c1) GROUP BY t1.c8 ORDER BY 2 ASC NULLS FIRST; + QUERY PLAN +----------------------------------------------------------------------------------------------------------------- + Foreign Scan + Output: (count(*)), t1.c8 + Foreign Namespace: Aggregate on ((mongo_fdw_regress.test_tbl1 t1) LEFT JOIN (mongo_fdw_regress.test_tbl2 t2)) +(3 rows) + +SELECT count(*), t1.c8 FROM fdw137_t1 t1 LEFT JOIN fdw137_t2 t2 ON (t1.c8 = t2.c1) GROUP BY t1.c8 ORDER BY 2 ASC NULLS FIRST; + count | c8 +-------+---- + 1 | + 3 | 10 + 5 | 20 + 6 | 30 + 1 | 60 +(5 rows) + +--Disable the GUC enable_join_pushdown. Shouldn't pushdown aggregate. +SET mongo_fdw.enable_join_pushdown to off; +EXPLAIN (VERBOSE, COSTS OFF) +SELECT count(*), t1.c8 FROM fdw137_t1 t1 LEFT JOIN fdw137_t2 t2 ON (t1.c8 = t2.c1) GROUP BY t1.c8 ORDER BY 2 ASC NULLS FIRST; + QUERY PLAN +-------------------------------------------------------------------------------------- + GroupAggregate + Output: count(*), t1.c8 + Group Key: t1.c8 + -> Merge Left Join + Output: t1.c8 + Merge Cond: (t1.c8 = t2.c1) + -> Foreign Scan on public.fdw137_t1 t1 + Output: t1._id, t1.c1, t1.c2, t1.c3, t1.c4, t1.c5, t1.c6, t1.c7, t1.c8 + Foreign Namespace: mongo_fdw_regress.test_tbl1 + -> Sort + Output: t2.c1 + Sort Key: t2.c1 NULLS FIRST + -> Foreign Scan on public.fdw137_t2 t2 + Output: t2.c1 + Foreign Namespace: mongo_fdw_regress.test_tbl2 +(15 rows) + +SELECT count(*), t1.c8 FROM fdw137_t1 t1 LEFT JOIN fdw137_t2 t2 ON (t1.c8 = t2.c1) GROUP BY t1.c8 ORDER BY 2 ASC NULLS FIRST; + count | c8 +-------+---- + 1 | + 3 | 10 + 5 | 20 + 6 | 30 + 1 | 60 +(5 rows) + +SET mongo_fdw.enable_join_pushdown to on; +--Disable the GUC enable_aggregate_pushdown. Shouldn't pushdown. +SET mongo_fdw.enable_aggregate_pushdown to false; +EXPLAIN (VERBOSE, COSTS OFF) +SELECT count(*), t1.c8 FROM fdw137_t1 t1 LEFT JOIN fdw137_t2 t2 ON (t1.c8 = t2.c1) GROUP BY t1.c8 ORDER BY 2 ASC NULLS FIRST; + QUERY PLAN +-------------------------------------------------------------------------------------------------------- + GroupAggregate + Output: count(*), t1.c8 + Group Key: t1.c8 + -> Foreign Scan + Output: t1.c8 + Foreign Namespace: (mongo_fdw_regress.test_tbl1 t1) LEFT JOIN (mongo_fdw_regress.test_tbl2 t2) +(6 rows) + +SELECT count(*), t1.c8 FROM fdw137_t1 t1 LEFT JOIN fdw137_t2 t2 ON (t1.c8 = t2.c1) GROUP BY t1.c8 ORDER BY 2 ASC NULLS FIRST; + count | c8 +-------+---- + 1 | + 3 | 10 + 5 | 20 + 6 | 30 + 1 | 60 +(5 rows) + +-- FDW-589: Test enable_order_by_pushdown option at server and table level. +SET mongo_fdw.enable_join_pushdown to true; +SET mongo_fdw.enable_aggregate_pushdown to true; +SET mongo_fdw.enable_order_by_pushdown to true; +ALTER SERVER mongo_server OPTIONS (ADD enable_order_by_pushdown 'true'); +ALTER FOREIGN TABLE fdw137_t1 OPTIONS (ADD enable_join_pushdown 'true'); +ALTER FOREIGN TABLE fdw137_t1 OPTIONS (SET enable_aggregate_pushdown 'true'); +ALTER FOREIGN TABLE fdw137_t1 OPTIONS (ADD enable_order_by_pushdown 'true'); +EXPLAIN (VERBOSE, COSTS OFF) +SELECT c2, sum(c1) FROM fdw137_t1 GROUP BY c1, c2 HAVING min(c1) > 500 ORDER BY 1 ASC NULLS FIRST; + QUERY PLAN +--------------------------------------------------------------------------- + Foreign Scan + Output: c2, (sum(c1)), c1 + Foreign Namespace: Aggregate on (mongo_fdw_regress.test_tbl1 fdw137_t1) +(3 rows) + +SELECT c2, sum(c1) FROM fdw137_t1 GROUP BY c1, c2 HAVING min(c1) > 500 ORDER BY 1 ASC NULLS FIRST; + c2 | sum +-------+------ + EMP10 | 1000 + EMP11 | 1100 + EMP12 | 1200 + EMP13 | 1300 + EMP14 | 1400 + EMP15 | 1500 + EMP16 | 1600 + EMP6 | 600 + EMP7 | 700 + EMP8 | 800 + EMP9 | 900 +(11 rows) + +ALTER FOREIGN TABLE fdw137_t2 OPTIONS (ADD enable_join_pushdown 'true'); +ALTER FOREIGN TABLE fdw137_t2 OPTIONS (SET enable_aggregate_pushdown 'true'); +ALTER FOREIGN TABLE fdw137_t2 OPTIONS (ADD enable_order_by_pushdown 'true'); +EXPLAIN (VERBOSE, COSTS OFF) +SELECT sum(t2.c1), t1.c8, avg(t1.c8) FROM fdw137_t1 t1 LEFT JOIN fdw137_t2 t2 ON (t1.c8 = t2.c1) WHERE t1.c8 > 10 GROUP BY t1.c8 HAVING avg(t1.c8)*1 > 10 + ORDER BY 2 ASC NULLS FIRST; + QUERY PLAN +----------------------------------------------------------------------------------------------------------------- + Foreign Scan + Output: (sum(t2.c1)), t1.c8, (avg(t1.c8)) + Foreign Namespace: Aggregate on ((mongo_fdw_regress.test_tbl1 t1) LEFT JOIN (mongo_fdw_regress.test_tbl2 t2)) +(3 rows) + +SELECT sum(t2.c1), t1.c8, avg(t1.c8) FROM fdw137_t1 t1 LEFT JOIN fdw137_t2 t2 ON (t1.c8 = t2.c1) WHERE t1.c8 > 10 GROUP BY t1.c8 HAVING avg(t1.c8)*1 > 10 + ORDER BY 2 ASC NULLS FIRST; + sum | c8 | avg +-----+----+----- + 100 | 20 | 20 + 180 | 30 | 30 + 0 | 60 | 60 +(3 rows) + +ALTER FOREIGN TABLE fdw137_t1 OPTIONS (SET enable_order_by_pushdown 'false'); +EXPLAIN (VERBOSE, COSTS OFF) +SELECT c2, sum(c1) FROM fdw137_t1 GROUP BY c1, c2 HAVING min(c1) > 500 ORDER BY 1 ASC NULLS FIRST; + QUERY PLAN +--------------------------------------------------------------------------------- + Sort + Output: c2, (sum(c1)), c1 + Sort Key: fdw137_t1.c2 NULLS FIRST + -> Foreign Scan + Output: c2, (sum(c1)), c1 + Foreign Namespace: Aggregate on (mongo_fdw_regress.test_tbl1 fdw137_t1) +(6 rows) + +SELECT c2, sum(c1) FROM fdw137_t1 GROUP BY c1, c2 HAVING min(c1) > 500 ORDER BY 1 ASC NULLS FIRST; + c2 | sum +-------+------ + EMP10 | 1000 + EMP11 | 1100 + EMP12 | 1200 + EMP13 | 1300 + EMP14 | 1400 + EMP15 | 1500 + EMP16 | 1600 + EMP6 | 600 + EMP7 | 700 + EMP8 | 800 + EMP9 | 900 +(11 rows) + +EXPLAIN (VERBOSE, COSTS OFF) +SELECT sum(t2.c1), t1.c8, avg(t1.c8) FROM fdw137_t1 t1 LEFT JOIN fdw137_t2 t2 ON (t1.c8 = t2.c1) WHERE t1.c8 > 10 GROUP BY t1.c8 HAVING avg(t1.c8)*1 > 10 + ORDER BY 2 ASC NULLS FIRST; + QUERY PLAN +----------------------------------------------------------------------------------------------------------------------- + Sort + Output: (sum(t2.c1)), t1.c8, (avg(t1.c8)) + Sort Key: t1.c8 NULLS FIRST + -> Foreign Scan + Output: (sum(t2.c1)), t1.c8, (avg(t1.c8)) + Foreign Namespace: Aggregate on ((mongo_fdw_regress.test_tbl1 t1) LEFT JOIN (mongo_fdw_regress.test_tbl2 t2)) +(6 rows) + +SELECT sum(t2.c1), t1.c8, avg(t1.c8) FROM fdw137_t1 t1 LEFT JOIN fdw137_t2 t2 ON (t1.c8 = t2.c1) WHERE t1.c8 > 10 GROUP BY t1.c8 HAVING avg(t1.c8)*1 > 10 + ORDER BY 2 ASC NULLS FIRST; + sum | c8 | avg +-----+----+----- + 100 | 20 | 20 + 180 | 30 | 30 + 0 | 60 | 60 +(3 rows) + +-- Test that setting option at table level does not affect the setting at +-- server level. +ALTER SERVER mongo_server OPTIONS (SET enable_order_by_pushdown 'false'); +ALTER FOREIGN TABLE fdw137_t1 OPTIONS (SET enable_order_by_pushdown 'true'); +EXPLAIN (VERBOSE, COSTS OFF) +SELECT c2, sum(c1) FROM fdw137_t1 GROUP BY c1, c2 HAVING min(c1) > 500 ORDER BY 1 ASC NULLS FIRST; + QUERY PLAN +--------------------------------------------------------------------------- + Foreign Scan + Output: c2, (sum(c1)), c1 + Foreign Namespace: Aggregate on (mongo_fdw_regress.test_tbl1 fdw137_t1) +(3 rows) + +SELECT c2, sum(c1) FROM fdw137_t1 GROUP BY c1, c2 HAVING min(c1) > 500 ORDER BY 1 ASC NULLS FIRST; + c2 | sum +-------+------ + EMP10 | 1000 + EMP11 | 1100 + EMP12 | 1200 + EMP13 | 1300 + EMP14 | 1400 + EMP15 | 1500 + EMP16 | 1600 + EMP6 | 600 + EMP7 | 700 + EMP8 | 800 + EMP9 | 900 +(11 rows) + +ALTER FOREIGN TABLE fdw137_t2 OPTIONS (SET enable_order_by_pushdown 'true'); +EXPLAIN (VERBOSE, COSTS OFF) +SELECT sum(t2.c1), t1.c8, avg(t1.c8) FROM fdw137_t1 t1 LEFT JOIN fdw137_t2 t2 ON (t1.c8 = t2.c1) WHERE t1.c8 > 10 GROUP BY t1.c8 HAVING avg(t1.c8)*1 > 10 + ORDER BY 2 ASC NULLS FIRST; + QUERY PLAN +----------------------------------------------------------------------------------------------------------------- + Foreign Scan + Output: (sum(t2.c1)), t1.c8, (avg(t1.c8)) + Foreign Namespace: Aggregate on ((mongo_fdw_regress.test_tbl1 t1) LEFT JOIN (mongo_fdw_regress.test_tbl2 t2)) +(3 rows) + +SELECT sum(t2.c1), t1.c8, avg(t1.c8) FROM fdw137_t1 t1 LEFT JOIN fdw137_t2 t2 ON (t1.c8 = t2.c1) WHERE t1.c8 > 10 GROUP BY t1.c8 HAVING avg(t1.c8)*1 > 10 + ORDER BY 2 ASC NULLS FIRST; + sum | c8 | avg +-----+----+----- + 100 | 20 | 20 + 180 | 30 | 30 + 0 | 60 | 60 +(3 rows) + +-- When option enable_aggregate_pushdown is disabled. Shouldn't pushdown +-- aggregate as well as ORDER BY too. +ALTER SERVER mongo_server OPTIONS (SET enable_order_by_pushdown 'true'); +ALTER FOREIGN TABLE fdw137_t1 OPTIONS (SET enable_aggregate_pushdown 'false'); +EXPLAIN (VERBOSE, COSTS OFF) +SELECT c2, sum(c1) FROM fdw137_t1 GROUP BY c1, c2 HAVING min(c1) > 500 ORDER BY 1 ASC NULLS FIRST; + QUERY PLAN +-------------------------------------------------------------- + Sort + Output: c2, (sum(c1)), c1 + Sort Key: fdw137_t1.c2 NULLS FIRST + -> HashAggregate + Output: c2, sum(c1), c1 + Group Key: fdw137_t1.c2, fdw137_t1.c1 + Filter: (min(fdw137_t1.c1) > 500) + -> Foreign Scan on public.fdw137_t1 + Output: _id, c1, c2, c3, c4, c5, c6, c7, c8 + Foreign Namespace: mongo_fdw_regress.test_tbl1 +(10 rows) + +SELECT c2, sum(c1) FROM fdw137_t1 GROUP BY c1, c2 HAVING min(c1) > 500 ORDER BY 1 ASC NULLS FIRST; + c2 | sum +-------+------ + EMP10 | 1000 + EMP11 | 1100 + EMP12 | 1200 + EMP13 | 1300 + EMP14 | 1400 + EMP15 | 1500 + EMP16 | 1600 + EMP6 | 600 + EMP7 | 700 + EMP8 | 800 + EMP9 | 900 +(11 rows) + +ALTER FOREIGN TABLE fdw137_t1 OPTIONS (SET enable_aggregate_pushdown 'true'); +-- Cleanup +DELETE FROM fdw137_t1 WHERE c8 IS NULL; +DELETE FROM fdw137_t1 WHERE c8 = 60; +DELETE FROM fdw137_t2 WHERE c1 IS NULL; +DELETE FROM fdw137_t2 WHERE c1 = 50; +DROP FOREIGN TABLE fdw137_t1; +DROP FOREIGN TABLE fdw137_t2; +DROP FOREIGN TABLE ftprt1_p1; +DROP FOREIGN TABLE ftprt1_p2; +DROP FOREIGN TABLE f_test_large; +DROP TABLE fprt1; +DROP USER MAPPING FOR public SERVER mongo_server; +DROP SERVER mongo_server; +DROP EXTENSION mongo_fdw; diff --git a/expected/join_pushdown_2.out b/expected/join_pushdown_2.out new file mode 100644 index 0000000..c664f77 --- /dev/null +++ b/expected/join_pushdown_2.out @@ -0,0 +1,2127 @@ +\set MONGO_HOST `echo \'"$MONGO_HOST"\'` +\set MONGO_PORT `echo \'"$MONGO_PORT"\'` +\set MONGO_USER_NAME `echo \'"$MONGO_USER_NAME"\'` +\set MONGO_PASS `echo \'"$MONGO_PWD"\'` +-- Before running this file user must create database mongo_fdw_regress on +-- MongoDB with all permission for MONGO_USER_NAME user with MONGO_PASS +-- password and ran mongodb_init.sh file to load collections. +\c contrib_regression +CREATE EXTENSION IF NOT EXISTS mongo_fdw; +CREATE SERVER mongo_server FOREIGN DATA WRAPPER mongo_fdw + OPTIONS (address :MONGO_HOST, port :MONGO_PORT); +CREATE USER MAPPING FOR public SERVER mongo_server; +CREATE SERVER mongo_server1 FOREIGN DATA WRAPPER mongo_fdw + OPTIONS (address :MONGO_HOST, port :MONGO_PORT); +CREATE USER MAPPING FOR public SERVER mongo_server1; +-- Create foreign tables. +CREATE FOREIGN TABLE f_test_tbl1 (_id NAME, c1 INTEGER, c2 TEXT, c3 CHAR(9), c4 INTEGER, c5 pg_catalog.Date, c6 DECIMAL, c7 INTEGER, c8 INTEGER) + SERVER mongo_server OPTIONS (database 'mongo_fdw_regress', collection 'test_tbl1'); +CREATE FOREIGN TABLE f_test_tbl2 (_id NAME, c1 INTEGER, c2 TEXT, c3 TEXT) + SERVER mongo_server OPTIONS (database 'mongo_fdw_regress', collection 'test_tbl2'); +CREATE FOREIGN TABLE f_test_tbl3 (_id NAME, c1 INTEGER, c2 TEXT, c3 TEXT) + SERVER mongo_server1 OPTIONS (database 'mongo_fdw_regress', collection 'test_tbl2'); +CREATE FOREIGN TABLE test_text ( __doc text) + SERVER mongo_server OPTIONS (database 'mongo_fdw_regress', collection 'warehouse'); +CREATE FOREIGN TABLE test_varchar ( __doc varchar) + SERVER mongo_server OPTIONS (database 'mongo_fdw_regress', collection 'warehouse'); +CREATE FOREIGN TABLE f_test_tbl4 (_id NAME, c1 INTEGER, c2 TEXT, c3 CHAR(9), c4 INTEGER, c5 pg_catalog.Date, c6 DECIMAL, c7 INTEGER, c8 INTEGER) + SERVER mongo_server1 OPTIONS (database 'mongo_fdw_regress', collection 'test_tbl1'); +INSERT INTO f_test_tbl1 VALUES (0, 1500, 'EMP15', 'FINANCE', 1300, '2000-12-25', 950.0, 400, 60); +INSERT INTO f_test_tbl1 VALUES (0, 1600, 'EMP16', 'ADMIN', 600); +INSERT INTO f_test_tbl2 VALUES (0, 50, 'TESTING', 'NASHIK'); +INSERT INTO f_test_tbl2 VALUES (0); +-- Create local table. +CREATE TABLE l_test_tbl1 AS + SELECT c1, c2, c3, c4, c5, c6, c7, c8 FROM f_test_tbl1; +-- Push down LEFT OUTER JOIN. +EXPLAIN (COSTS OFF) +SELECT d.c1, d.c2, e.c1, e.c2, e.c6, e.c8 + FROM f_test_tbl2 d LEFT OUTER JOIN f_test_tbl1 e ON d.c1 = e.c8 ORDER BY 1 ASC NULLS FIRST, 3 ASC NULLS FIRST; + QUERY PLAN +------------------------------------------------------------------------------------------------ + Foreign Scan + Foreign Namespace: (mongo_fdw_regress.test_tbl2 d) LEFT JOIN (mongo_fdw_regress.test_tbl1 e) +(2 rows) + +SELECT d.c1, d.c2, e.c1, e.c2, e.c6, e.c8 + FROM f_test_tbl2 d LEFT OUTER JOIN f_test_tbl1 e ON d.c1 = e.c8 ORDER BY 1 ASC NULLS FIRST, 3 ASC NULLS FIRST; + c1 | c2 | c1 | c2 | c6 | c8 +----+----------------+------+-------+---------+---- + | | | | | + 10 | DEVELOPMENT | 700 | EMP7 | 2450.34 | 10 + 10 | DEVELOPMENT | 900 | EMP9 | 5000 | 10 + 10 | DEVELOPMENT | 1400 | EMP14 | 1300 | 10 + 20 | ADMINISTRATION | 100 | EMP1 | 800.3 | 20 + 20 | ADMINISTRATION | 400 | EMP4 | 2975 | 20 + 20 | ADMINISTRATION | 800 | EMP8 | 3000 | 20 + 20 | ADMINISTRATION | 1100 | EMP11 | 1100 | 20 + 20 | ADMINISTRATION | 1300 | EMP13 | 3000 | 20 + 30 | SALES | 200 | EMP2 | 1600 | 30 + 30 | SALES | 300 | EMP3 | 1250 | 30 + 30 | SALES | 500 | EMP5 | 1250.23 | 30 + 30 | SALES | 600 | EMP6 | 2850 | 30 + 30 | SALES | 1000 | EMP10 | 1500 | 30 + 30 | SALES | 1200 | EMP12 | 950 | 30 + 40 | HR | | | | + 50 | TESTING | | | | +(17 rows) + +EXPLAIN (COSTS OFF) +SELECT d.c1, d.c2, e.c1, e.c2, e.c6, e.c8 + FROM f_test_tbl1 e LEFT OUTER JOIN f_test_tbl2 d ON d.c1 = e.c8 ORDER BY 1 ASC NULLS FIRST, 3 ASC NULLS FIRST; + QUERY PLAN +------------------------------------------------------------------------------------------------ + Foreign Scan + Foreign Namespace: (mongo_fdw_regress.test_tbl1 e) LEFT JOIN (mongo_fdw_regress.test_tbl2 d) +(2 rows) + +SELECT d.c1, d.c2, e.c1, e.c2, e.c6, e.c8 + FROM f_test_tbl1 e LEFT OUTER JOIN f_test_tbl2 d ON e.c8 = d.c1 ORDER BY 1 ASC NULLS FIRST, 3 ASC NULLS FIRST; + c1 | c2 | c1 | c2 | c6 | c8 +----+----------------+------+-------+---------+---- + 20 | ADMINISTRATION | 100 | EMP1 | 800.3 | 20 + 30 | SALES | 200 | EMP2 | 1600 | 30 + 30 | SALES | 300 | EMP3 | 1250 | 30 + 20 | ADMINISTRATION | 400 | EMP4 | 2975 | 20 + 30 | SALES | 500 | EMP5 | 1250.23 | 30 + 30 | SALES | 600 | EMP6 | 2850 | 30 + 10 | DEVELOPMENT | 700 | EMP7 | 2450.34 | 10 + 20 | ADMINISTRATION | 800 | EMP8 | 3000 | 20 + 10 | DEVELOPMENT | 900 | EMP9 | 5000 | 10 + 30 | SALES | 1000 | EMP10 | 1500 | 30 + 20 | ADMINISTRATION | 1100 | EMP11 | 1100 | 20 + 30 | SALES | 1200 | EMP12 | 950 | 30 + 20 | ADMINISTRATION | 1300 | EMP13 | 3000 | 20 + 10 | DEVELOPMENT | 1400 | EMP14 | 1300 | 10 + | | 1500 | EMP15 | 950 | 60 + | | 1600 | EMP16 | | +(16 rows) + +EXPLAIN (COSTS OFF) +SELECT d.c1, d.c2, e.c1, e.c2, e.c6, e.c8 + FROM f_test_tbl2 d LEFT OUTER JOIN f_test_tbl1 e ON (d.c1 = e.c8 AND e.c4 > d.c1 OR e.c2 < d.c3) ORDER BY 1 ASC NULLS FIRST, 3 ASC NULLS FIRST OFFSET 50; + QUERY PLAN +------------------------------------------------------------------------------------------------ + Foreign Scan + Foreign Namespace: (mongo_fdw_regress.test_tbl2 d) LEFT JOIN (mongo_fdw_regress.test_tbl1 e) +(2 rows) + +SELECT d.c1, d.c2, e.c1, e.c2, e.c6, e.c8 + FROM f_test_tbl2 d LEFT OUTER JOIN f_test_tbl1 e ON (d.c1 = e.c8 AND e.c4 > d.c1 OR e.c2 < d.c3) ORDER BY 1 ASC NULLS FIRST, 3 ASC NULLS FIRST OFFSET 50; + c1 | c2 | c1 | c2 | c6 | c8 +----+---------+------+-------+---------+---- + 40 | HR | 1300 | EMP13 | 3000 | 20 + 40 | HR | 1400 | EMP14 | 1300 | 10 + 40 | HR | 1500 | EMP15 | 950 | 60 + 40 | HR | 1600 | EMP16 | | + 50 | TESTING | 100 | EMP1 | 800.3 | 20 + 50 | TESTING | 200 | EMP2 | 1600 | 30 + 50 | TESTING | 300 | EMP3 | 1250 | 30 + 50 | TESTING | 400 | EMP4 | 2975 | 20 + 50 | TESTING | 500 | EMP5 | 1250.23 | 30 + 50 | TESTING | 600 | EMP6 | 2850 | 30 + 50 | TESTING | 700 | EMP7 | 2450.34 | 10 + 50 | TESTING | 800 | EMP8 | 3000 | 20 + 50 | TESTING | 900 | EMP9 | 5000 | 10 + 50 | TESTING | 1000 | EMP10 | 1500 | 30 + 50 | TESTING | 1100 | EMP11 | 1100 | 20 + 50 | TESTING | 1200 | EMP12 | 950 | 30 + 50 | TESTING | 1300 | EMP13 | 3000 | 20 + 50 | TESTING | 1400 | EMP14 | 1300 | 10 + 50 | TESTING | 1500 | EMP15 | 950 | 60 + 50 | TESTING | 1600 | EMP16 | | +(20 rows) + +EXPLAIN (COSTS OFF) +SELECT d.c1, d.c2, e.c1, e.c2, e.c6, e.c8 + FROM f_test_tbl2 d LEFT OUTER JOIN f_test_tbl1 e ON (d.c1 = e.c8 AND e.c4 > d.c1 AND e.c2 < d.c3) ORDER BY 1 ASC NULLS FIRST, 3 ASC NULLS FIRST; + QUERY PLAN +------------------------------------------------------------------------------------------------ + Foreign Scan + Foreign Namespace: (mongo_fdw_regress.test_tbl2 d) LEFT JOIN (mongo_fdw_regress.test_tbl1 e) +(2 rows) + +SELECT d.c1, d.c2, e.c1, e.c2, e.c6, e.c8 + FROM f_test_tbl2 d LEFT OUTER JOIN f_test_tbl1 e ON (d.c1 = e.c8 AND e.c4 > d.c1 AND e.c2 < d.c3) ORDER BY 1 ASC NULLS FIRST, 3 ASC NULLS FIRST; + c1 | c2 | c1 | c2 | c6 | c8 +----+----------------+------+-------+---------+---- + | | | | | + 10 | DEVELOPMENT | 700 | EMP7 | 2450.34 | 10 + 10 | DEVELOPMENT | 1400 | EMP14 | 1300 | 10 + 20 | ADMINISTRATION | | | | + 30 | SALES | 200 | EMP2 | 1600 | 30 + 30 | SALES | 300 | EMP3 | 1250 | 30 + 30 | SALES | 500 | EMP5 | 1250.23 | 30 + 30 | SALES | 600 | EMP6 | 2850 | 30 + 30 | SALES | 1000 | EMP10 | 1500 | 30 + 30 | SALES | 1200 | EMP12 | 950 | 30 + 40 | HR | | | | + 50 | TESTING | | | | +(12 rows) + +-- With ORDER BY pushdown disabled. +SET mongo_fdw.enable_order_by_pushdown TO OFF; +EXPLAIN (COSTS OFF) +SELECT d.c1, d.c2, e.c1, e.c2, e.c6, e.c8 + FROM f_test_tbl2 d LEFT OUTER JOIN f_test_tbl1 e ON (d.c1 = e.c8 AND e.c4 > d.c1 AND e.c2 < d.c3) ORDER BY 1 ASC NULLS FIRST, 3 ASC NULLS FIRST; + QUERY PLAN +------------------------------------------------------------------------------------------------------ + Sort + Sort Key: d.c1 NULLS FIRST, e.c1 NULLS FIRST + -> Foreign Scan + Foreign Namespace: (mongo_fdw_regress.test_tbl2 d) LEFT JOIN (mongo_fdw_regress.test_tbl1 e) +(4 rows) + +SELECT d.c1, d.c2, e.c1, e.c2, e.c6, e.c8 + FROM f_test_tbl2 d LEFT OUTER JOIN f_test_tbl1 e ON (d.c1 = e.c8 AND e.c4 > d.c1 AND e.c2 < d.c3) ORDER BY 1 ASC NULLS FIRST, 3 ASC NULLS FIRST; + c1 | c2 | c1 | c2 | c6 | c8 +----+----------------+------+-------+---------+---- + | | | | | + 10 | DEVELOPMENT | 700 | EMP7 | 2450.34 | 10 + 10 | DEVELOPMENT | 1400 | EMP14 | 1300 | 10 + 20 | ADMINISTRATION | | | | + 30 | SALES | 200 | EMP2 | 1600 | 30 + 30 | SALES | 300 | EMP3 | 1250 | 30 + 30 | SALES | 500 | EMP5 | 1250.23 | 30 + 30 | SALES | 600 | EMP6 | 2850 | 30 + 30 | SALES | 1000 | EMP10 | 1500 | 30 + 30 | SALES | 1200 | EMP12 | 950 | 30 + 40 | HR | | | | + 50 | TESTING | | | | +(12 rows) + +SET mongo_fdw.enable_order_by_pushdown TO ON; +-- Column comparing with 'Constant' pushed down. +EXPLAIN (COSTS OFF) +SELECT d.c1, d.c2, e.c1, e.c2, e.c6, e.c8 + FROM f_test_tbl2 d LEFT OUTER JOIN f_test_tbl1 e ON d.c1 = 20 ORDER BY 1 ASC NULLS FIRST, 3 ASC NULLS FIRST; + QUERY PLAN +------------------------------------------------------------------------------------------------ + Foreign Scan + Foreign Namespace: (mongo_fdw_regress.test_tbl2 d) LEFT JOIN (mongo_fdw_regress.test_tbl1 e) +(2 rows) + +SELECT d.c1, d.c2, e.c1, e.c2, e.c6, e.c8 + FROM f_test_tbl2 d LEFT OUTER JOIN f_test_tbl1 e ON d.c1 = 20 ORDER BY 1 ASC NULLS FIRST, 3 ASC NULLS FIRST; + c1 | c2 | c1 | c2 | c6 | c8 +----+----------------+------+-------+---------+---- + | | | | | + 10 | DEVELOPMENT | | | | + 20 | ADMINISTRATION | 100 | EMP1 | 800.3 | 20 + 20 | ADMINISTRATION | 200 | EMP2 | 1600 | 30 + 20 | ADMINISTRATION | 300 | EMP3 | 1250 | 30 + 20 | ADMINISTRATION | 400 | EMP4 | 2975 | 20 + 20 | ADMINISTRATION | 500 | EMP5 | 1250.23 | 30 + 20 | ADMINISTRATION | 600 | EMP6 | 2850 | 30 + 20 | ADMINISTRATION | 700 | EMP7 | 2450.34 | 10 + 20 | ADMINISTRATION | 800 | EMP8 | 3000 | 20 + 20 | ADMINISTRATION | 900 | EMP9 | 5000 | 10 + 20 | ADMINISTRATION | 1000 | EMP10 | 1500 | 30 + 20 | ADMINISTRATION | 1100 | EMP11 | 1100 | 20 + 20 | ADMINISTRATION | 1200 | EMP12 | 950 | 30 + 20 | ADMINISTRATION | 1300 | EMP13 | 3000 | 20 + 20 | ADMINISTRATION | 1400 | EMP14 | 1300 | 10 + 20 | ADMINISTRATION | 1500 | EMP15 | 950 | 60 + 20 | ADMINISTRATION | 1600 | EMP16 | | + 30 | SALES | | | | + 40 | HR | | | | + 50 | TESTING | | | | +(21 rows) + +-- Push down RIGHT OUTER JOIN. +EXPLAIN (COSTS OFF) +SELECT d.c1, d.c2, e.c1, e.c2, e.c6, e.c8 + FROM f_test_tbl2 d RIGHT OUTER JOIN f_test_tbl1 e ON d.c1 = e.c8 ORDER BY 1 ASC NULLS FIRST, 3 ASC NULLS FIRST; + QUERY PLAN +------------------------------------------------------------------------------------------------ + Foreign Scan + Foreign Namespace: (mongo_fdw_regress.test_tbl1 e) LEFT JOIN (mongo_fdw_regress.test_tbl2 d) +(2 rows) + +SELECT d.c1, d.c2, e.c1, e.c2, e.c6, e.c8 + FROM f_test_tbl2 d RIGHT OUTER JOIN f_test_tbl1 e ON d.c1 = e.c8 ORDER BY 1 ASC NULLS FIRST, 3 ASC NULLS FIRST; + c1 | c2 | c1 | c2 | c6 | c8 +----+----------------+------+-------+---------+---- + 20 | ADMINISTRATION | 100 | EMP1 | 800.3 | 20 + 30 | SALES | 200 | EMP2 | 1600 | 30 + 30 | SALES | 300 | EMP3 | 1250 | 30 + 20 | ADMINISTRATION | 400 | EMP4 | 2975 | 20 + 30 | SALES | 500 | EMP5 | 1250.23 | 30 + 30 | SALES | 600 | EMP6 | 2850 | 30 + 10 | DEVELOPMENT | 700 | EMP7 | 2450.34 | 10 + 20 | ADMINISTRATION | 800 | EMP8 | 3000 | 20 + 10 | DEVELOPMENT | 900 | EMP9 | 5000 | 10 + 30 | SALES | 1000 | EMP10 | 1500 | 30 + 20 | ADMINISTRATION | 1100 | EMP11 | 1100 | 20 + 30 | SALES | 1200 | EMP12 | 950 | 30 + 20 | ADMINISTRATION | 1300 | EMP13 | 3000 | 20 + 10 | DEVELOPMENT | 1400 | EMP14 | 1300 | 10 + | | 1500 | EMP15 | 950 | 60 + | | 1600 | EMP16 | | +(16 rows) + +EXPLAIN (COSTS OFF) +SELECT d.c1, d.c2, e.c1, e.c2, e.c6, e.c8 + FROM f_test_tbl1 e RIGHT OUTER JOIN f_test_tbl2 d ON e.c8 = d.c1 ORDER BY 1 ASC NULLS FIRST, 3 ASC NULLS FIRST; + QUERY PLAN +------------------------------------------------------------------------------------------------ + Foreign Scan + Foreign Namespace: (mongo_fdw_regress.test_tbl2 d) LEFT JOIN (mongo_fdw_regress.test_tbl1 e) +(2 rows) + +SELECT d.c1, d.c2, e.c1, e.c2, e.c6, e.c8 + FROM f_test_tbl1 e RIGHT OUTER JOIN f_test_tbl2 d ON e.c8 = d.c1 ORDER BY 1 ASC NULLS FIRST, 3 ASC NULLS FIRST; + c1 | c2 | c1 | c2 | c6 | c8 +----+----------------+------+-------+---------+---- + | | | | | + 10 | DEVELOPMENT | 700 | EMP7 | 2450.34 | 10 + 10 | DEVELOPMENT | 900 | EMP9 | 5000 | 10 + 10 | DEVELOPMENT | 1400 | EMP14 | 1300 | 10 + 20 | ADMINISTRATION | 100 | EMP1 | 800.3 | 20 + 20 | ADMINISTRATION | 400 | EMP4 | 2975 | 20 + 20 | ADMINISTRATION | 800 | EMP8 | 3000 | 20 + 20 | ADMINISTRATION | 1100 | EMP11 | 1100 | 20 + 20 | ADMINISTRATION | 1300 | EMP13 | 3000 | 20 + 30 | SALES | 200 | EMP2 | 1600 | 30 + 30 | SALES | 300 | EMP3 | 1250 | 30 + 30 | SALES | 500 | EMP5 | 1250.23 | 30 + 30 | SALES | 600 | EMP6 | 2850 | 30 + 30 | SALES | 1000 | EMP10 | 1500 | 30 + 30 | SALES | 1200 | EMP12 | 950 | 30 + 40 | HR | | | | + 50 | TESTING | | | | +(17 rows) + +EXPLAIN (COSTS OFF) +SELECT d.c1, d.c2, e.c1, e.c2, e.c6, e.c8 + FROM f_test_tbl2 d RIGHT OUTER JOIN f_test_tbl1 e ON (d.c1 = e.c8 OR e.c4 > d.c1 OR e.c2 < d.c3) ORDER BY 1, 3 OFFSET 60; + QUERY PLAN +------------------------------------------------------------------------------------------------------------ + Limit + -> Sort + Sort Key: d.c1, e.c1 + -> Foreign Scan + Foreign Namespace: (mongo_fdw_regress.test_tbl1 e) LEFT JOIN (mongo_fdw_regress.test_tbl2 d) +(5 rows) + +SELECT d.c1, d.c2, e.c1, e.c2, e.c6, e.c8 + FROM f_test_tbl2 d RIGHT OUTER JOIN f_test_tbl1 e ON (d.c1 = e.c8 OR e.c4 > d.c1 OR e.c2 < d.c3) ORDER BY 1, 3 OFFSET 60; + c1 | c2 | c1 | c2 | c6 | c8 +----+---------+------+-------+---------+---- + 40 | HR | 1400 | EMP14 | 1300 | 10 + 40 | HR | 1500 | EMP15 | 950 | 60 + 40 | HR | 1600 | EMP16 | | + 50 | TESTING | 100 | EMP1 | 800.3 | 20 + 50 | TESTING | 200 | EMP2 | 1600 | 30 + 50 | TESTING | 300 | EMP3 | 1250 | 30 + 50 | TESTING | 400 | EMP4 | 2975 | 20 + 50 | TESTING | 500 | EMP5 | 1250.23 | 30 + 50 | TESTING | 600 | EMP6 | 2850 | 30 + 50 | TESTING | 700 | EMP7 | 2450.34 | 10 + 50 | TESTING | 800 | EMP8 | 3000 | 20 + 50 | TESTING | 900 | EMP9 | 5000 | 10 + 50 | TESTING | 1000 | EMP10 | 1500 | 30 + 50 | TESTING | 1100 | EMP11 | 1100 | 20 + 50 | TESTING | 1200 | EMP12 | 950 | 30 + 50 | TESTING | 1300 | EMP13 | 3000 | 20 + 50 | TESTING | 1400 | EMP14 | 1300 | 10 + 50 | TESTING | 1500 | EMP15 | 950 | 60 + 50 | TESTING | 1600 | EMP16 | | +(19 rows) + +EXPLAIN (COSTS OFF) +SELECT d.c1, d.c2, e.c1, e.c2, e.c6, e.c8 + FROM f_test_tbl2 d LEFT OUTER JOIN f_test_tbl1 e ON ((d.c1 = e.c8 OR e.c4 > d.c1) AND e.c2 < d.c3) ORDER BY 1, 3 OFFSET 60; + QUERY PLAN +------------------------------------------------------------------------------------------------------------ + Limit + -> Sort + Sort Key: d.c1, e.c1 + -> Foreign Scan + Foreign Namespace: (mongo_fdw_regress.test_tbl2 d) LEFT JOIN (mongo_fdw_regress.test_tbl1 e) +(5 rows) + +SELECT d.c1, d.c2, e.c1, e.c2, e.c6, e.c8 + FROM f_test_tbl2 d LEFT OUTER JOIN f_test_tbl1 e ON ((d.c1 = e.c8 OR e.c4 > d.c1) OR e.c2 < d.c3) ORDER BY 1, 3 OFFSET 60; + c1 | c2 | c1 | c2 | c6 | c8 +----+---------+------+-------+---------+---- + 40 | HR | 1400 | EMP14 | 1300 | 10 + 40 | HR | 1500 | EMP15 | 950 | 60 + 40 | HR | 1600 | EMP16 | | + 50 | TESTING | 100 | EMP1 | 800.3 | 20 + 50 | TESTING | 200 | EMP2 | 1600 | 30 + 50 | TESTING | 300 | EMP3 | 1250 | 30 + 50 | TESTING | 400 | EMP4 | 2975 | 20 + 50 | TESTING | 500 | EMP5 | 1250.23 | 30 + 50 | TESTING | 600 | EMP6 | 2850 | 30 + 50 | TESTING | 700 | EMP7 | 2450.34 | 10 + 50 | TESTING | 800 | EMP8 | 3000 | 20 + 50 | TESTING | 900 | EMP9 | 5000 | 10 + 50 | TESTING | 1000 | EMP10 | 1500 | 30 + 50 | TESTING | 1100 | EMP11 | 1100 | 20 + 50 | TESTING | 1200 | EMP12 | 950 | 30 + 50 | TESTING | 1300 | EMP13 | 3000 | 20 + 50 | TESTING | 1400 | EMP14 | 1300 | 10 + 50 | TESTING | 1500 | EMP15 | 950 | 60 + 50 | TESTING | 1600 | EMP16 | | + | | | | | +(20 rows) + +-- Column comparing with 'Constant' pushed down. +EXPLAIN (COSTS OFF) +SELECT d.c1, d.c2, e.c1, e.c2, e.c6, e.c8 + FROM f_test_tbl2 d RIGHT OUTER JOIN f_test_tbl1 e ON d.c1 = 20 ORDER BY 1 ASC NULLS FIRST, 3 ASC NULLS FIRST; + QUERY PLAN +------------------------------------------------------------------------------------------------ + Foreign Scan + Foreign Namespace: (mongo_fdw_regress.test_tbl1 e) LEFT JOIN (mongo_fdw_regress.test_tbl2 d) +(2 rows) + +SELECT d.c1, d.c2, e.c1, e.c2, e.c6, e.c8 + FROM f_test_tbl2 d RIGHT OUTER JOIN f_test_tbl1 e ON (d.c1 = 20 AND e.c2 = 'EMP1') ORDER BY 1 ASC NULLS FIRST, 3 ASC NULLS FIRST; + c1 | c2 | c1 | c2 | c6 | c8 +----+----------------+------+-------+---------+---- + 20 | ADMINISTRATION | 100 | EMP1 | 800.3 | 20 + | | 200 | EMP2 | 1600 | 30 + | | 300 | EMP3 | 1250 | 30 + | | 400 | EMP4 | 2975 | 20 + | | 500 | EMP5 | 1250.23 | 30 + | | 600 | EMP6 | 2850 | 30 + | | 700 | EMP7 | 2450.34 | 10 + | | 800 | EMP8 | 3000 | 20 + | | 900 | EMP9 | 5000 | 10 + | | 1000 | EMP10 | 1500 | 30 + | | 1100 | EMP11 | 1100 | 20 + | | 1200 | EMP12 | 950 | 30 + | | 1300 | EMP13 | 3000 | 20 + | | 1400 | EMP14 | 1300 | 10 + | | 1500 | EMP15 | 950 | 60 + | | 1600 | EMP16 | | +(16 rows) + +-- Push INNER JOIN. +EXPLAIN (COSTS OFF) +SELECT d.c1, d.c2, e.c1, e.c2, e.c6, e.c8 + FROM f_test_tbl2 d INNER JOIN f_test_tbl1 e ON d.c1 = e.c8 ORDER BY 1, 3; + QUERY PLAN +------------------------------------------------------------------------------------------------------- + Sort + Sort Key: d.c1, e.c1 + -> Foreign Scan + Foreign Namespace: (mongo_fdw_regress.test_tbl2 d) INNER JOIN (mongo_fdw_regress.test_tbl1 e) +(4 rows) + +SELECT d.c1, d.c2, e.c1, e.c2, e.c6, e.c8 + FROM f_test_tbl2 d INNER JOIN f_test_tbl1 e ON d.c1 = e.c8 ORDER BY 1, 3; + c1 | c2 | c1 | c2 | c6 | c8 +----+----------------+------+-------+---------+---- + 10 | DEVELOPMENT | 700 | EMP7 | 2450.34 | 10 + 10 | DEVELOPMENT | 900 | EMP9 | 5000 | 10 + 10 | DEVELOPMENT | 1400 | EMP14 | 1300 | 10 + 20 | ADMINISTRATION | 100 | EMP1 | 800.3 | 20 + 20 | ADMINISTRATION | 400 | EMP4 | 2975 | 20 + 20 | ADMINISTRATION | 800 | EMP8 | 3000 | 20 + 20 | ADMINISTRATION | 1100 | EMP11 | 1100 | 20 + 20 | ADMINISTRATION | 1300 | EMP13 | 3000 | 20 + 30 | SALES | 200 | EMP2 | 1600 | 30 + 30 | SALES | 300 | EMP3 | 1250 | 30 + 30 | SALES | 500 | EMP5 | 1250.23 | 30 + 30 | SALES | 600 | EMP6 | 2850 | 30 + 30 | SALES | 1000 | EMP10 | 1500 | 30 + 30 | SALES | 1200 | EMP12 | 950 | 30 +(14 rows) + +EXPLAIN (COSTS OFF) +SELECT d.c1, d.c2, e.c1, e.c2, e.c6, e.c8 + FROM f_test_tbl2 d INNER JOIN f_test_tbl1 e ON ((d.c1 = e.c8 OR e.c4 > d.c1) AND e.c2 < d.c3) ORDER BY 1, 3 OFFSET 60; + QUERY PLAN +------------------------------------------------------------------------------------------------------------- + Limit + -> Sort + Sort Key: d.c1, e.c1 + -> Foreign Scan + Foreign Namespace: (mongo_fdw_regress.test_tbl2 d) INNER JOIN (mongo_fdw_regress.test_tbl1 e) +(5 rows) + +SELECT d.c1, d.c2, e.c1, e.c2, e.c6, e.c8 + FROM f_test_tbl2 d INNER JOIN f_test_tbl1 e ON ((d.c1 = e.c8 OR e.c4 > d.c1) OR e.c2 < d.c3) ORDER BY 1, 3 OFFSET 60; + c1 | c2 | c1 | c2 | c6 | c8 +----+---------+------+-------+---------+---- + 40 | HR | 1400 | EMP14 | 1300 | 10 + 40 | HR | 1500 | EMP15 | 950 | 60 + 40 | HR | 1600 | EMP16 | | + 50 | TESTING | 100 | EMP1 | 800.3 | 20 + 50 | TESTING | 200 | EMP2 | 1600 | 30 + 50 | TESTING | 300 | EMP3 | 1250 | 30 + 50 | TESTING | 400 | EMP4 | 2975 | 20 + 50 | TESTING | 500 | EMP5 | 1250.23 | 30 + 50 | TESTING | 600 | EMP6 | 2850 | 30 + 50 | TESTING | 700 | EMP7 | 2450.34 | 10 + 50 | TESTING | 800 | EMP8 | 3000 | 20 + 50 | TESTING | 900 | EMP9 | 5000 | 10 + 50 | TESTING | 1000 | EMP10 | 1500 | 30 + 50 | TESTING | 1100 | EMP11 | 1100 | 20 + 50 | TESTING | 1200 | EMP12 | 950 | 30 + 50 | TESTING | 1300 | EMP13 | 3000 | 20 + 50 | TESTING | 1400 | EMP14 | 1300 | 10 + 50 | TESTING | 1500 | EMP15 | 950 | 60 + 50 | TESTING | 1600 | EMP16 | | +(19 rows) + +EXPLAIN (COSTS OFF) +SELECT d.c1, d.c2, e.c1, e.c2, e.c6, e.c8 + FROM f_test_tbl2 d INNER JOIN f_test_tbl1 e ON (d.c1 = e.c8 OR e.c2 < d.c3) ORDER BY 1, 3 OFFSET 60; + QUERY PLAN +------------------------------------------------------------------------------------------------------------- + Limit + -> Sort + Sort Key: d.c1, e.c1 + -> Foreign Scan + Foreign Namespace: (mongo_fdw_regress.test_tbl2 d) INNER JOIN (mongo_fdw_regress.test_tbl1 e) +(5 rows) + +SELECT d.c1, d.c2, e.c1, e.c2, e.c6, e.c8 + FROM f_test_tbl2 d INNER JOIN f_test_tbl1 e ON (d.c1 = e.c8 OR e.c2 < d.c3) ORDER BY 1, 3 OFFSET 60; + c1 | c2 | c1 | c2 | c6 | c8 +----+---------+------+-------+------+---- + 50 | TESTING | 800 | EMP8 | 3000 | 20 + 50 | TESTING | 900 | EMP9 | 5000 | 10 + 50 | TESTING | 1000 | EMP10 | 1500 | 30 + 50 | TESTING | 1100 | EMP11 | 1100 | 20 + 50 | TESTING | 1200 | EMP12 | 950 | 30 + 50 | TESTING | 1300 | EMP13 | 3000 | 20 + 50 | TESTING | 1400 | EMP14 | 1300 | 10 + 50 | TESTING | 1500 | EMP15 | 950 | 60 + 50 | TESTING | 1600 | EMP16 | | +(9 rows) + +-- Column comparing with 'Constant' pushed down. +EXPLAIN (COSTS OFF) +SELECT d.c1, d.c2, e.c1, e.c2, e.c6, e.c8 + FROM f_test_tbl2 d INNER JOIN f_test_tbl1 e ON (d.c1 = e.c8 AND d.c1 = 20 OR e.c2 = 'EMP1') ORDER BY 1, 3; + QUERY PLAN +------------------------------------------------------------------------------------------------------- + Sort + Sort Key: d.c1, e.c1 + -> Foreign Scan + Foreign Namespace: (mongo_fdw_regress.test_tbl2 d) INNER JOIN (mongo_fdw_regress.test_tbl1 e) +(4 rows) + +SELECT d.c1, d.c2, e.c1, e.c2, e.c6, e.c8 + FROM f_test_tbl2 d INNER JOIN f_test_tbl1 e ON (d.c1 = e.c8 AND d.c1 = 20 OR e.c2 = 'EMP1') ORDER BY 1, 3; + c1 | c2 | c1 | c2 | c6 | c8 +----+----------------+------+-------+-------+---- + 10 | DEVELOPMENT | 100 | EMP1 | 800.3 | 20 + 20 | ADMINISTRATION | 100 | EMP1 | 800.3 | 20 + 20 | ADMINISTRATION | 400 | EMP4 | 2975 | 20 + 20 | ADMINISTRATION | 800 | EMP8 | 3000 | 20 + 20 | ADMINISTRATION | 1100 | EMP11 | 1100 | 20 + 20 | ADMINISTRATION | 1300 | EMP13 | 3000 | 20 + 30 | SALES | 100 | EMP1 | 800.3 | 20 + 40 | HR | 100 | EMP1 | 800.3 | 20 + 50 | TESTING | 100 | EMP1 | 800.3 | 20 + | | 100 | EMP1 | 800.3 | 20 +(10 rows) + +-- INNER JOIN with WHERE clause. Should execute where condition separately +-- (NOT added into join clauses) on remote side. +EXPLAIN (COSTS OFF) +SELECT d.c1, e.c1 + FROM f_test_tbl1 d JOIN f_test_tbl2 e ON (d.c8 = e.c1) WHERE d.c1 = 100 ORDER BY e.c3 DESC NULLS LAST, d.c1 DESC NULLS LAST; + QUERY PLAN +------------------------------------------------------------------------------------------------- + Foreign Scan + Foreign Namespace: (mongo_fdw_regress.test_tbl1 d) INNER JOIN (mongo_fdw_regress.test_tbl2 e) +(2 rows) + +SELECT d.c1, e.c1 + FROM f_test_tbl1 d JOIN f_test_tbl2 e ON (d.c8 = e.c1) WHERE d.c1 = 100 ORDER BY e.c3 DESC NULLS LAST, d.c1 DESC NULLS LAST; + c1 | c1 +-----+---- + 100 | 20 +(1 row) + +-- INNER JOIN in which join clause is not pushable but WHERE condition is +-- pushable with join clause 'TRUE'. +EXPLAIN (COSTS OFF) +SELECT d.c1, e.c1 + FROM f_test_tbl1 d JOIN f_test_tbl2 e ON (abs(d.c8) = e.c1) WHERE d.c1 = 100 ORDER BY e.c3 DESC NULLS LAST, d.c1 DESC NULLS LAST; + QUERY PLAN +------------------------------------------------------------------------------------------------- + Foreign Scan + Filter: (abs(c8) = c1) + Foreign Namespace: (mongo_fdw_regress.test_tbl1 d) INNER JOIN (mongo_fdw_regress.test_tbl2 e) +(3 rows) + +SELECT d.c1, e.c1 + FROM f_test_tbl1 d JOIN f_test_tbl2 e ON (abs(d.c8) = e.c1) WHERE d.c1 = 100 ORDER BY e.c3 DESC NULLS LAST, d.c1 DESC NULLS LAST; + c1 | c1 +-----+---- + 100 | 20 +(1 row) + +-- With ORDER BY pushdown disabled. +SET mongo_fdw.enable_order_by_pushdown TO OFF; +EXPLAIN (COSTS OFF) +SELECT d.c1, e.c1 + FROM f_test_tbl1 d JOIN f_test_tbl2 e ON (abs(d.c8) = e.c1) WHERE d.c1 = 100 ORDER BY e.c3 DESC NULLS LAST, d.c1 DESC NULLS LAST; + QUERY PLAN +------------------------------------------------------------------------------------------------------- + Sort + Sort Key: e.c3 DESC NULLS LAST + -> Foreign Scan + Filter: (abs(c8) = c1) + Foreign Namespace: (mongo_fdw_regress.test_tbl1 d) INNER JOIN (mongo_fdw_regress.test_tbl2 e) +(5 rows) + +SELECT d.c1, e.c1 + FROM f_test_tbl1 d JOIN f_test_tbl2 e ON (abs(d.c8) = e.c1) WHERE d.c1 = 100 ORDER BY e.c3 DESC NULLS LAST, d.c1 DESC NULLS LAST; + c1 | c1 +-----+---- + 100 | 20 +(1 row) + +SET mongo_fdw.enable_order_by_pushdown TO ON; +SET enable_mergejoin TO OFF; +SET enable_nestloop TO OFF; +-- Local-Foreign table joins. +EXPLAIN (COSTS OFF) +SELECT d.c1, d.c2, e.c1, e.c2, e.c6, e.c8 + FROM f_test_tbl2 d LEFT OUTER JOIN l_test_tbl1 e ON d.c1 = e.c8 ORDER BY 1 ASC NULLS FIRST, 3 ASC NULLS FIRST; + QUERY PLAN +-------------------------------------------------------------- + Sort + Sort Key: d.c1 NULLS FIRST, e.c1 NULLS FIRST + -> Hash Left Join + Hash Cond: (d.c1 = e.c8) + -> Foreign Scan on f_test_tbl2 d + Foreign Namespace: mongo_fdw_regress.test_tbl2 + -> Hash + -> Seq Scan on l_test_tbl1 e +(8 rows) + +SELECT d.c1, d.c2, e.c1, e.c2, e.c6, e.c8 + FROM f_test_tbl2 d LEFT OUTER JOIN l_test_tbl1 e ON d.c1 = e.c8 ORDER BY 1 ASC NULLS FIRST, 3 ASC NULLS FIRST; + c1 | c2 | c1 | c2 | c6 | c8 +----+----------------+------+-------+---------+---- + | | | | | + 10 | DEVELOPMENT | 700 | EMP7 | 2450.34 | 10 + 10 | DEVELOPMENT | 900 | EMP9 | 5000 | 10 + 10 | DEVELOPMENT | 1400 | EMP14 | 1300 | 10 + 20 | ADMINISTRATION | 100 | EMP1 | 800.3 | 20 + 20 | ADMINISTRATION | 400 | EMP4 | 2975 | 20 + 20 | ADMINISTRATION | 800 | EMP8 | 3000 | 20 + 20 | ADMINISTRATION | 1100 | EMP11 | 1100 | 20 + 20 | ADMINISTRATION | 1300 | EMP13 | 3000 | 20 + 30 | SALES | 200 | EMP2 | 1600 | 30 + 30 | SALES | 300 | EMP3 | 1250 | 30 + 30 | SALES | 500 | EMP5 | 1250.23 | 30 + 30 | SALES | 600 | EMP6 | 2850 | 30 + 30 | SALES | 1000 | EMP10 | 1500 | 30 + 30 | SALES | 1200 | EMP12 | 950 | 30 + 40 | HR | | | | + 50 | TESTING | | | | +(17 rows) + +RESET enable_mergejoin; +RESET enable_nestloop; +-- JOIN in sub-query, should be pushed down. +EXPLAIN (COSTS OFF) +SELECT l.c1, l.c6, l.c8 + FROM l_test_tbl1 l + WHERE l.c1 IN (SELECT f1.c1 FROM f_test_tbl1 f1 LEFT JOIN f_test_tbl2 f2 ON (f1.c8 = f2.c1)) ORDER BY 1 ASC NULLS FIRST, 3 ASC NULLS FIRST; + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------------- + Sort + Sort Key: l.c1 NULLS FIRST, l.c8 NULLS FIRST + -> Hash Join + Hash Cond: (l.c1 = f1.c1) + -> Seq Scan on l_test_tbl1 l + -> Hash + -> HashAggregate + Group Key: f1.c1 + -> Foreign Scan + Foreign Namespace: (mongo_fdw_regress.test_tbl1 f1) LEFT JOIN (mongo_fdw_regress.test_tbl2 f2) +(10 rows) + +SELECT l.c1, l.c6, l.c8 + FROM l_test_tbl1 l + WHERE l.c1 IN (SELECT f1.c1 FROM f_test_tbl1 f1 LEFT JOIN f_test_tbl2 f2 ON (f1.c8 = f2.c1)) ORDER BY 1 ASC NULLS FIRST, 3 ASC NULLS FIRST; + c1 | c6 | c8 +------+---------+---- + 100 | 800.3 | 20 + 200 | 1600 | 30 + 300 | 1250 | 30 + 400 | 2975 | 20 + 500 | 1250.23 | 30 + 600 | 2850 | 30 + 700 | 2450.34 | 10 + 800 | 3000 | 20 + 900 | 5000 | 10 + 1000 | 1500 | 30 + 1100 | 1100 | 20 + 1200 | 950 | 30 + 1300 | 3000 | 20 + 1400 | 1300 | 10 + 1500 | 950 | 60 + 1600 | | +(16 rows) + +EXPLAIN (COSTS OFF) +SELECT l.c1, l.c6, l.c8 + FROM l_test_tbl1 l + WHERE l.c1 = (SELECT f1.c1 FROM f_test_tbl1 f1 LEFT JOIN f_test_tbl2 f2 ON (f1.c8 = f2.c1) LIMIT 1) ORDER BY 1, 3; + QUERY PLAN +---------------------------------------------------------------------------------------------------------- + Sort + Sort Key: l.c8 + InitPlan 1 + -> Foreign Scan + Foreign Namespace: (mongo_fdw_regress.test_tbl1 f1) LEFT JOIN (mongo_fdw_regress.test_tbl2 f2) + -> Seq Scan on l_test_tbl1 l + Filter: (c1 = (InitPlan 1).col1) +(7 rows) + +SELECT l.c1, l.c6, l.c8 + FROM l_test_tbl1 l + WHERE l.c1 = (SELECT f1.c1 FROM f_test_tbl1 f1 LEFT JOIN f_test_tbl2 f2 ON (f1.c8 = f2.c1) LIMIT 1) ORDER BY 1, 3; + c1 | c6 | c8 +-----+-------+---- + 100 | 800.3 | 20 +(1 row) + +EXPLAIN (COSTS OFF) +SELECT l.c1, l.c6, l.c8 + FROM l_test_tbl1 l + WHERE l.c1 = (SELECT f1.c1 FROM f_test_tbl1 f1 INNER JOIN f_test_tbl2 f2 ON (f1.c8 = f2.c1) LIMIT 1) ORDER BY 1, 3; + QUERY PLAN +----------------------------------------------------------------------------------------------------------- + Sort + Sort Key: l.c8 + InitPlan 1 + -> Foreign Scan + Foreign Namespace: (mongo_fdw_regress.test_tbl1 f1) INNER JOIN (mongo_fdw_regress.test_tbl2 f2) + -> Seq Scan on l_test_tbl1 l + Filter: (c1 = (InitPlan 1).col1) +(7 rows) + +SELECT l.c1, l.c6, l.c8 + FROM l_test_tbl1 l + WHERE l.c1 = (SELECT f1.c1 FROM f_test_tbl1 f1 INNER JOIN f_test_tbl2 f2 ON (f1.c8 = f2.c1) LIMIT 1) ORDER BY 1, 3; + c1 | c6 | c8 +-----+-------+---- + 100 | 800.3 | 20 +(1 row) + +-- Execute JOIN through PREPARE statement. +PREPARE pre_stmt_left_join AS +SELECT d.c1, d.c2, e.c1, e.c2, e.c6, e.c8 + FROM f_test_tbl2 d LEFT OUTER JOIN f_test_tbl1 e ON (d.c1 = e.c8 OR e.c4 > d.c1) ORDER BY 1, 3 OFFSET 70; +EXPLAIN (COSTS OFF) +EXECUTE pre_stmt_left_join; + QUERY PLAN +------------------------------------------------------------------------------------------------------------ + Limit + -> Sort + Sort Key: d.c1, e.c1 + -> Foreign Scan + Foreign Namespace: (mongo_fdw_regress.test_tbl2 d) LEFT JOIN (mongo_fdw_regress.test_tbl1 e) +(5 rows) + +EXECUTE pre_stmt_left_join; + c1 | c2 | c1 | c2 | c6 | c8 +----+---------+------+-------+------+---- + 50 | TESTING | 1100 | EMP11 | 1100 | 20 + 50 | TESTING | 1200 | EMP12 | 950 | 30 + 50 | TESTING | 1300 | EMP13 | 3000 | 20 + 50 | TESTING | 1400 | EMP14 | 1300 | 10 + 50 | TESTING | 1500 | EMP15 | 950 | 60 + 50 | TESTING | 1600 | EMP16 | | + | | | | | +(7 rows) + +PREPARE pre_stmt_inner_join AS +SELECT d.c1, d.c2, e.c1, e.c2, e.c6, e.c8 + FROM f_test_tbl2 d INNER JOIN f_test_tbl1 e ON (d.c1 = e.c8 OR e.c4 > d.c1) ORDER BY 1, 3 OFFSET 70; +EXPLAIN (COSTS OFF) +EXECUTE pre_stmt_inner_join; + QUERY PLAN +------------------------------------------------------------------------------------------------------------- + Limit + -> Sort + Sort Key: d.c1, e.c1 + -> Foreign Scan + Foreign Namespace: (mongo_fdw_regress.test_tbl2 d) INNER JOIN (mongo_fdw_regress.test_tbl1 e) +(5 rows) + +EXECUTE pre_stmt_inner_join; + c1 | c2 | c1 | c2 | c6 | c8 +----+---------+------+-------+------+---- + 50 | TESTING | 1100 | EMP11 | 1100 | 20 + 50 | TESTING | 1200 | EMP12 | 950 | 30 + 50 | TESTING | 1300 | EMP13 | 3000 | 20 + 50 | TESTING | 1400 | EMP14 | 1300 | 10 + 50 | TESTING | 1500 | EMP15 | 950 | 60 + 50 | TESTING | 1600 | EMP16 | | +(6 rows) + +-- join + WHERE clause push-down. +EXPLAIN (COSTS OFF) +SELECT d.c1, d.c2, e.c1, e.c2, e.c6, e.c8 + FROM f_test_tbl2 d LEFT OUTER JOIN f_test_tbl1 e ON d.c1 = e.c8 WHERE d.c1 = 10 ORDER BY 1 DESC NULLS LAST, 3 DESC NULLS LAST; + QUERY PLAN +------------------------------------------------------------------------------------------------ + Foreign Scan + Foreign Namespace: (mongo_fdw_regress.test_tbl2 d) LEFT JOIN (mongo_fdw_regress.test_tbl1 e) +(2 rows) + +SELECT d.c1, d.c2, e.c1, e.c2, e.c6, e.c8 + FROM f_test_tbl2 d LEFT OUTER JOIN f_test_tbl1 e ON d.c1 = e.c8 WHERE d.c1 = 10 ORDER BY 1 DESC NULLS LAST, 3 DESC NULLS LAST; + c1 | c2 | c1 | c2 | c6 | c8 +----+-------------+------+-------+---------+---- + 10 | DEVELOPMENT | 700 | EMP7 | 2450.34 | 10 + 10 | DEVELOPMENT | 900 | EMP9 | 5000 | 10 + 10 | DEVELOPMENT | 1400 | EMP14 | 1300 | 10 +(3 rows) + +EXPLAIN (COSTS OFF) +SELECT d.c1, d.c2, e.c1, e.c2, e.c6, e.c8 + FROM f_test_tbl2 d RIGHT OUTER JOIN f_test_tbl1 e ON d.c1 = e.c8 WHERE e.c8 = 10 ORDER BY 1, 3; + QUERY PLAN +------------------------------------------------------------------------------------------------------ + Sort + Sort Key: d.c1, e.c1 + -> Foreign Scan + Foreign Namespace: (mongo_fdw_regress.test_tbl1 e) LEFT JOIN (mongo_fdw_regress.test_tbl2 d) +(4 rows) + +SELECT d.c1, d.c2, e.c1, e.c2, e.c6, e.c8 + FROM f_test_tbl2 d RIGHT OUTER JOIN f_test_tbl1 e ON d.c1 = e.c8 WHERE e.c8 = 10 ORDER BY 1, 3; + c1 | c2 | c1 | c2 | c6 | c8 +----+-------------+------+-------+---------+---- + 10 | DEVELOPMENT | 700 | EMP7 | 2450.34 | 10 + 10 | DEVELOPMENT | 900 | EMP9 | 5000 | 10 + 10 | DEVELOPMENT | 1400 | EMP14 | 1300 | 10 +(3 rows) + +EXPLAIN (COSTS OFF) +SELECT d.c1, d.c2, e.c1, e.c2, e.c6, e.c8 + FROM f_test_tbl2 d INNER JOIN f_test_tbl1 e ON d.c1 = e.c8 WHERE d.c2 = 'SALES' ORDER BY 1, 3; + QUERY PLAN +------------------------------------------------------------------------------------------------------- + Sort + Sort Key: d.c1, e.c1 + -> Foreign Scan + Foreign Namespace: (mongo_fdw_regress.test_tbl2 d) INNER JOIN (mongo_fdw_regress.test_tbl1 e) +(4 rows) + +SELECT d.c1, d.c2, e.c1, e.c2, e.c6, e.c8 + FROM f_test_tbl2 d INNER JOIN f_test_tbl1 e ON d.c1 = e.c8 WHERE d.c2 = 'SALES' ORDER BY 1, 3; + c1 | c2 | c1 | c2 | c6 | c8 +----+-------+------+-------+---------+---- + 30 | SALES | 200 | EMP2 | 1600 | 30 + 30 | SALES | 300 | EMP3 | 1250 | 30 + 30 | SALES | 500 | EMP5 | 1250.23 | 30 + 30 | SALES | 600 | EMP6 | 2850 | 30 + 30 | SALES | 1000 | EMP10 | 1500 | 30 + 30 | SALES | 1200 | EMP12 | 950 | 30 +(6 rows) + +EXPLAIN (COSTS OFF) +SELECT d.c1, d.c2, e.c1, e.c2, e.c6, e.c8 + FROM f_test_tbl2 d INNER JOIN f_test_tbl1 e ON d.c1 = e.c8 WHERE e.c2 = 'EMP2' ORDER BY 1, 3; + QUERY PLAN +------------------------------------------------------------------------------------------------------- + Sort + Sort Key: d.c1, e.c1 + -> Foreign Scan + Foreign Namespace: (mongo_fdw_regress.test_tbl2 d) INNER JOIN (mongo_fdw_regress.test_tbl1 e) +(4 rows) + +SELECT d.c1, d.c2, e.c1, e.c2, e.c6, e.c8 + FROM f_test_tbl2 d INNER JOIN f_test_tbl1 e ON d.c1 = e.c8 WHERE e.c2 = 'EMP2' ORDER BY 1, 3; + c1 | c2 | c1 | c2 | c6 | c8 +----+-------+-----+------+------+---- + 30 | SALES | 200 | EMP2 | 1600 | 30 +(1 row) + +EXPLAIN (COSTS OFF) +SELECT d.c1, d.c2, e.c1, e.c2, e.c6, e.c8 + FROM f_test_tbl2 d INNER JOIN f_test_tbl1 e ON (d.c1 = e.c8 AND d.c1 = 20 OR e.c2 = 'EMP1') WHERE d.c1 = 10 OR e.c8 = 30 ORDER BY 1, 3; + QUERY PLAN +------------------------------------------------------------------------------------------------------- + Sort + Sort Key: d.c1, e.c1 + -> Foreign Scan + Foreign Namespace: (mongo_fdw_regress.test_tbl2 d) INNER JOIN (mongo_fdw_regress.test_tbl1 e) +(4 rows) + +SELECT d.c1, d.c2, e.c1, e.c2, e.c6, e.c8 + FROM f_test_tbl2 d INNER JOIN f_test_tbl1 e ON (d.c1 = e.c8 AND d.c1 = 20 OR e.c2 = 'EMP1') WHERE d.c1 = 10 OR e.c8 = 30 ORDER BY 1, 3; + c1 | c2 | c1 | c2 | c6 | c8 +----+-------------+-----+------+-------+---- + 10 | DEVELOPMENT | 100 | EMP1 | 800.3 | 20 +(1 row) + +EXPLAIN (COSTS OFF) +SELECT d.c1, d.c2, e.c1, e.c2, d.c6, d.c8 + FROM f_test_tbl1 d LEFT JOIN f_test_tbl2 e ON (e.c1 = d.c8 AND (e.c1 = 20 OR d.c2 = 'EMP1')) WHERE e.c1 = 20 AND d.c8 = 20 ORDER BY 1, 3; + QUERY PLAN +------------------------------------------------------------------------------------------------------- + Sort + Sort Key: d.c1 + -> Foreign Scan + Foreign Namespace: (mongo_fdw_regress.test_tbl1 d) INNER JOIN (mongo_fdw_regress.test_tbl2 e) +(4 rows) + +SELECT d.c1, d.c2, e.c1, e.c2, d.c6, d.c8 + FROM f_test_tbl1 d LEFT JOIN f_test_tbl2 e ON (e.c1 = d.c8 AND (e.c1 = 20 OR d.c2 = 'EMP1')) WHERE e.c1 = 20 AND d.c8 = 20 ORDER BY 1, 3; + c1 | c2 | c1 | c2 | c6 | c8 +------+-------+----+----------------+-------+---- + 100 | EMP1 | 20 | ADMINISTRATION | 800.3 | 20 + 400 | EMP4 | 20 | ADMINISTRATION | 2975 | 20 + 800 | EMP8 | 20 | ADMINISTRATION | 3000 | 20 + 1100 | EMP11 | 20 | ADMINISTRATION | 1100 | 20 + 1300 | EMP13 | 20 | ADMINISTRATION | 3000 | 20 +(5 rows) + +EXPLAIN (COSTS OFF) +SELECT d.c1, d.c2, d.c5, e.c1, e.c2 + FROM f_test_tbl1 d LEFT JOIN f_test_tbl2 e ON (e.c1 = d.c8 AND (d.c5 = '02-22-1981' OR d.c5 = '12-17-1980')) ORDER BY 1, 3; + QUERY PLAN +------------------------------------------------------------------------------------------------------ + Sort + Sort Key: d.c1, d.c5 + -> Foreign Scan + Foreign Namespace: (mongo_fdw_regress.test_tbl1 d) LEFT JOIN (mongo_fdw_regress.test_tbl2 e) +(4 rows) + +SELECT d.c1, d.c2, d.c5, e.c1, e.c2 + FROM f_test_tbl1 d LEFT JOIN f_test_tbl2 e ON (e.c1 = d.c8 AND (d.c5 = '02-22-1981' OR d.c5 = '12-17-1980')) ORDER BY 1, 3; + c1 | c2 | c5 | c1 | c2 +------+-------+------------+----+---------------- + 100 | EMP1 | 12-17-1980 | 20 | ADMINISTRATION + 200 | EMP2 | 02-20-1981 | | + 300 | EMP3 | 02-22-1981 | 30 | SALES + 400 | EMP4 | 04-02-1981 | | + 500 | EMP5 | 09-28-1981 | | + 600 | EMP6 | 05-01-1981 | | + 700 | EMP7 | 06-09-1981 | | + 800 | EMP8 | 04-19-1987 | | + 900 | EMP9 | 11-17-1981 | | + 1000 | EMP10 | 09-08-1980 | | + 1100 | EMP11 | 05-23-1987 | | + 1200 | EMP12 | 12-03-1981 | | + 1300 | EMP13 | 12-03-1981 | | + 1400 | EMP14 | 01-23-1982 | | + 1500 | EMP15 | 12-25-2000 | | + 1600 | EMP16 | | | +(16 rows) + +EXPLAIN (COSTS OFF) +SELECT d.c1, d.c2, d.c5, e.c1, e.c2 + FROM f_test_tbl1 d LEFT JOIN f_test_tbl2 e ON (e.c1 = d.c8) WHERE d.c5 = '02-22-1981' ORDER BY 1; + QUERY PLAN +------------------------------------------------------------------------------------------------------ + Sort + Sort Key: d.c1 + -> Foreign Scan + Foreign Namespace: (mongo_fdw_regress.test_tbl1 d) LEFT JOIN (mongo_fdw_regress.test_tbl2 e) +(4 rows) + +SELECT d.c1, d.c2, d.c5, e.c1, e.c2 + FROM f_test_tbl1 d LEFT JOIN f_test_tbl2 e ON (e.c1 = d.c8) WHERE d.c5 = '02-22-1981' ORDER BY 1; + c1 | c2 | c5 | c1 | c2 +-----+------+------------+----+------- + 300 | EMP3 | 02-22-1981 | 30 | SALES +(1 row) + +EXPLAIN (COSTS OFF) +SELECT d.c1, d.c2, e.c1, e.c2, e.c6, e.c8 + FROM f_test_tbl2 d LEFT JOIN f_test_tbl1 e ON (d.c1 = e.c8 AND d.c1 = 20 OR e.c2 = 'EMP1') WHERE d.c1 = 10 OR e.c8 = 30 ORDER BY 1 DESC NULLS LAST, 3 DESC NULLS LAST; + QUERY PLAN +------------------------------------------------------------------------------------------------ + Foreign Scan + Filter: ((c1 = 10) OR (c8 = 30)) + Foreign Namespace: (mongo_fdw_regress.test_tbl2 d) LEFT JOIN (mongo_fdw_regress.test_tbl1 e) +(3 rows) + +SELECT d.c1, d.c2, e.c1, e.c2, e.c6, e.c8 + FROM f_test_tbl2 d LEFT JOIN f_test_tbl1 e ON (d.c1 = e.c8 AND d.c1 = 20 OR e.c2 = 'EMP1') WHERE d.c1 = 10 OR e.c8 = 30 ORDER BY 1 DESC NULLS LAST, 3 DESC NULLS LAST; + c1 | c2 | c1 | c2 | c6 | c8 +----+-------------+-----+------+-------+---- + 10 | DEVELOPMENT | 100 | EMP1 | 800.3 | 20 +(1 row) + +-- Natural join, should push-down. +EXPLAIN (COSTS OFF) +SELECT d.c1, d.c2, d.c5, e.c1, e.c2 + FROM f_test_tbl1 d NATURAL JOIN f_test_tbl1 e WHERE e.c1 > d.c8 ORDER BY 1; + QUERY PLAN +------------------------------------------------------------------------------------------------------- + Sort + Sort Key: d.c1 + -> Foreign Scan + Foreign Namespace: (mongo_fdw_regress.test_tbl1 d) INNER JOIN (mongo_fdw_regress.test_tbl1 e) +(4 rows) + +SELECT d.c1, d.c2, d.c5, e.c1, e.c2 + FROM f_test_tbl1 d NATURAL JOIN f_test_tbl1 e WHERE e.c1 > d.c8 ORDER BY 1; + c1 | c2 | c5 | c1 | c2 +------+-------+------------+------+------- + 100 | EMP1 | 12-17-1980 | 100 | EMP1 + 200 | EMP2 | 02-20-1981 | 200 | EMP2 + 300 | EMP3 | 02-22-1981 | 300 | EMP3 + 400 | EMP4 | 04-02-1981 | 400 | EMP4 + 500 | EMP5 | 09-28-1981 | 500 | EMP5 + 600 | EMP6 | 05-01-1981 | 600 | EMP6 + 700 | EMP7 | 06-09-1981 | 700 | EMP7 + 800 | EMP8 | 04-19-1987 | 800 | EMP8 + 1000 | EMP10 | 09-08-1980 | 1000 | EMP10 + 1100 | EMP11 | 05-23-1987 | 1100 | EMP11 + 1200 | EMP12 | 12-03-1981 | 1200 | EMP12 + 1300 | EMP13 | 12-03-1981 | 1300 | EMP13 + 1400 | EMP14 | 01-23-1982 | 1400 | EMP14 + 1500 | EMP15 | 12-25-2000 | 1500 | EMP15 +(14 rows) + +-- Self join, should push-down. +EXPLAIN (COSTS OFF) +SELECT d.c1, d.c2, d.c5, e.c1, e.c2 + FROM f_test_tbl1 d INNER JOIN f_test_tbl1 e ON e.c8 = d.c8 ORDER BY 1 OFFSET 65; + QUERY PLAN +------------------------------------------------------------------------------------------------------------- + Limit + -> Sort + Sort Key: d.c1 + -> Foreign Scan + Foreign Namespace: (mongo_fdw_regress.test_tbl1 d) INNER JOIN (mongo_fdw_regress.test_tbl1 e) +(5 rows) + +SELECT d.c1, d.c2, d.c5, e.c1, e.c2 + FROM f_test_tbl1 d INNER JOIN f_test_tbl1 e ON e.c8 = d.c8 ORDER BY 1 OFFSET 65; + c1 | c2 | c5 | c1 | c2 +------+-------+------------+------+------- + 1300 | EMP13 | 12-03-1981 | 1100 | EMP11 + 1300 | EMP13 | 12-03-1981 | 1300 | EMP13 + 1400 | EMP14 | 01-23-1982 | 700 | EMP7 + 1400 | EMP14 | 01-23-1982 | 900 | EMP9 + 1400 | EMP14 | 01-23-1982 | 1400 | EMP14 + 1500 | EMP15 | 12-25-2000 | 1500 | EMP15 +(6 rows) + +-- Join in CTE. +-- Explain plan difference between v11 (or pre) and later. +EXPLAIN (COSTS false, VERBOSE) +WITH t (c1_1, c1_3, c2_1) AS ( + SELECT d.c1, d.c3, e.c1 + FROM f_test_tbl1 d JOIN f_test_tbl2 e ON (d.c8 = e.c1) +) SELECT c1_1, c2_1 FROM t ORDER BY c1_3, c1_1; + QUERY PLAN +------------------------------------------------------------------------------------------------------- + Sort + Output: d.c1, e.c1, d.c3 + Sort Key: d.c3, d.c1 + -> Foreign Scan + Output: d.c1, e.c1, d.c3 + Foreign Namespace: (mongo_fdw_regress.test_tbl1 d) INNER JOIN (mongo_fdw_regress.test_tbl2 e) +(6 rows) + +WITH t (c1_1, c1_3, c2_1) AS ( + SELECT d.c1, d.c3, e.c1 + FROM f_test_tbl1 d JOIN f_test_tbl2 e ON (d.c8 = e.c1) +) SELECT c1_1, c2_1 FROM t ORDER BY c1_3, c1_1; + c1_1 | c2_1 +------+------ + 100 | 20 + 1100 | 20 + 1200 | 30 + 1400 | 10 + 800 | 20 + 1300 | 20 + 900 | 10 + 400 | 20 + 600 | 30 + 700 | 10 + 200 | 30 + 300 | 30 + 500 | 30 + 1000 | 30 +(14 rows) + +-- WHERE with boolean expression. Should push-down. +EXPLAIN (COSTS OFF) +SELECT d.c1, d.c2, d.c5, e.c1, e.c2 + FROM f_test_tbl2 e LEFT JOIN f_test_tbl1 d ON (e.c1 = d.c8) WHERE d.c5 = '02-22-1981' OR d.c5 = '12-17-1980' ORDER BY 1; + QUERY PLAN +------------------------------------------------------------------------------------------------------- + Sort + Sort Key: d.c1 + -> Foreign Scan + Foreign Namespace: (mongo_fdw_regress.test_tbl2 e) INNER JOIN (mongo_fdw_regress.test_tbl1 d) +(4 rows) + +SELECT d.c1, d.c2, d.c5, e.c1, e.c2 + FROM f_test_tbl2 e LEFT JOIN f_test_tbl1 d ON (e.c1 = d.c8) WHERE d.c5 = '02-22-1981' OR d.c5 = '12-17-1980' ORDER BY 1; + c1 | c2 | c5 | c1 | c2 +-----+------+------------+----+---------------- + 100 | EMP1 | 12-17-1980 | 20 | ADMINISTRATION + 300 | EMP3 | 02-22-1981 | 30 | SALES +(2 rows) + +-- Nested joins(Don't push-down nested join) +SET enable_mergejoin TO OFF; +EXPLAIN (COSTS OFF) +SELECT d.c1, d.c2, d.c5, e.c1, e.c2 + FROM f_test_tbl1 d LEFT JOIN f_test_tbl2 e ON (e.c1 = d.c8) LEFT JOIN f_test_tbl1 f ON (f.c8 = e.c1) ORDER BY d.c1 OFFSET 65 ; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------ + Limit + -> Sort + Sort Key: d.c1 + -> Hash Left Join + Hash Cond: (e.c1 = f.c8) + -> Foreign Scan + Foreign Namespace: (mongo_fdw_regress.test_tbl1 d) LEFT JOIN (mongo_fdw_regress.test_tbl2 e) + -> Hash + -> Foreign Scan on f_test_tbl1 f + Foreign Namespace: mongo_fdw_regress.test_tbl1 +(10 rows) + +SELECT d.c1, d.c2, d.c5, e.c1, e.c2 + FROM f_test_tbl1 d LEFT JOIN f_test_tbl2 e ON (e.c1 = d.c8) LEFT JOIN f_test_tbl1 f ON (f.c8 = e.c1) ORDER BY d.c1 OFFSET 65; + c1 | c2 | c5 | c1 | c2 +------+-------+------------+----+---------------- + 1300 | EMP13 | 12-03-1981 | 20 | ADMINISTRATION + 1300 | EMP13 | 12-03-1981 | 20 | ADMINISTRATION + 1400 | EMP14 | 01-23-1982 | 10 | DEVELOPMENT + 1400 | EMP14 | 01-23-1982 | 10 | DEVELOPMENT + 1400 | EMP14 | 01-23-1982 | 10 | DEVELOPMENT + 1500 | EMP15 | 12-25-2000 | | + 1600 | EMP16 | | | +(7 rows) + +RESET enable_mergejoin; +-- Not supported expressions won't push-down(e.g. function expression, etc.) +EXPLAIN (COSTS OFF) +SELECT d.c1, d.c2, e.c1, e.c2, e.c6, e.c8 + FROM f_test_tbl2 d LEFT OUTER JOIN f_test_tbl1 e ON (ABS(d.c1) = e.c8) ORDER BY 1, 3; + QUERY PLAN +-------------------------------------------------------------------- + Sort + Sort Key: d.c1, e.c1 + -> Merge Left Join + Merge Cond: ((abs(d.c1)) = e.c8) + -> Sort + Sort Key: (abs(d.c1)) + -> Foreign Scan on f_test_tbl2 d + Foreign Namespace: mongo_fdw_regress.test_tbl2 + -> Sort + Sort Key: e.c8 + -> Foreign Scan on f_test_tbl1 e + Foreign Namespace: mongo_fdw_regress.test_tbl1 +(12 rows) + +SELECT d.c1, d.c2, e.c1, e.c2, e.c6, e.c8 + FROM f_test_tbl2 d LEFT OUTER JOIN f_test_tbl1 e ON (ABS(d.c1) = e.c8) ORDER BY 1, 3; + c1 | c2 | c1 | c2 | c6 | c8 +----+----------------+------+-------+---------+---- + 10 | DEVELOPMENT | 700 | EMP7 | 2450.34 | 10 + 10 | DEVELOPMENT | 900 | EMP9 | 5000 | 10 + 10 | DEVELOPMENT | 1400 | EMP14 | 1300 | 10 + 20 | ADMINISTRATION | 100 | EMP1 | 800.3 | 20 + 20 | ADMINISTRATION | 400 | EMP4 | 2975 | 20 + 20 | ADMINISTRATION | 800 | EMP8 | 3000 | 20 + 20 | ADMINISTRATION | 1100 | EMP11 | 1100 | 20 + 20 | ADMINISTRATION | 1300 | EMP13 | 3000 | 20 + 30 | SALES | 200 | EMP2 | 1600 | 30 + 30 | SALES | 300 | EMP3 | 1250 | 30 + 30 | SALES | 500 | EMP5 | 1250.23 | 30 + 30 | SALES | 600 | EMP6 | 2850 | 30 + 30 | SALES | 1000 | EMP10 | 1500 | 30 + 30 | SALES | 1200 | EMP12 | 950 | 30 + 40 | HR | | | | + 50 | TESTING | | | | + | | | | | +(17 rows) + +-- Don't pushdown when whole row reference is involved. +EXPLAIN (COSTS OFF) +SELECT d, e + FROM f_test_tbl1 d LEFT JOIN f_test_tbl2 e ON (e.c1 = d.c8) LEFT JOIN f_test_tbl1 f ON (f.c8 = e.c1) ORDER BY e.c1 OFFSET 65; + QUERY PLAN +-------------------------------------------------------------------------------- + Limit + -> Merge Left Join + Merge Cond: (e.c1 = f.c8) + -> Sort + Sort Key: e.c1 + -> Hash Left Join + Hash Cond: (d.c8 = e.c1) + -> Foreign Scan on f_test_tbl1 d + Foreign Namespace: mongo_fdw_regress.test_tbl1 + -> Hash + -> Foreign Scan on f_test_tbl2 e + Foreign Namespace: mongo_fdw_regress.test_tbl2 + -> Sort + Sort Key: f.c8 + -> Foreign Scan on f_test_tbl1 f + Foreign Namespace: mongo_fdw_regress.test_tbl1 +(16 rows) + +-- Don't pushdown when full document retrieval is involved. +EXPLAIN (COSTS OFF) +SELECT json_data.key AS key1, json_data.value AS value1 + FROM test_text, test_varchar, json_each_text(test_text.__doc::json) AS json_data WHERE key NOT IN ('_id') ORDER BY json_data.key COLLATE "C"; + QUERY PLAN +-------------------------------------------------------------------- + Sort + Sort Key: json_data.key COLLATE "C" + -> Nested Loop + -> Nested Loop + -> Foreign Scan on test_text + Foreign Namespace: mongo_fdw_regress.warehouse + -> Function Scan on json_each_text json_data + Filter: (key <> '_id'::text) + -> Materialize + -> Foreign Scan on test_varchar + Foreign Namespace: mongo_fdw_regress.warehouse +(11 rows) + +SELECT json_data.key AS key1, json_data.value AS value1 + FROM test_text, test_varchar, json_each_text(test_text.__doc::json) AS json_data WHERE key NOT IN ('_id') ORDER BY json_data.key COLLATE "C"; + key1 | value1 +-------------------+----------------------------- + warehouse_created | { "$date" : 1418368330000 } + warehouse_created | { "$date" : 1418368330000 } + warehouse_created | { "$date" : 1447229590000 } + warehouse_created | { "$date" : 1447229590000 } + warehouse_id | 2 + warehouse_id | 1 + warehouse_id | 1 + warehouse_id | 2 + warehouse_name | Laptop + warehouse_name | Laptop + warehouse_name | UPS + warehouse_name | UPS +(12 rows) + +-- Join two tables from two different foreign servers. +EXPLAIN (COSTS OFF) +SELECT d.c1, e.c1 + FROM f_test_tbl2 d LEFT OUTER JOIN f_test_tbl3 e ON d.c1 = e.c1 ORDER BY 1; + QUERY PLAN +-------------------------------------------------------------- + Merge Left Join + Merge Cond: (d.c1 = e.c1) + -> Sort + Sort Key: d.c1 + -> Foreign Scan on f_test_tbl2 d + Foreign Namespace: mongo_fdw_regress.test_tbl2 + -> Sort + Sort Key: e.c1 + -> Foreign Scan on f_test_tbl3 e + Foreign Namespace: mongo_fdw_regress.test_tbl2 +(10 rows) + +-- SEMI JOIN, not pushed down +EXPLAIN (COSTS OFF) +SELECT d.c2 + FROM f_test_tbl1 d WHERE EXISTS (SELECT 1 FROM f_test_tbl2 e WHERE d.c8 = e.c1) ORDER BY d.c2 LIMIT 10; + QUERY PLAN +-------------------------------------------------------------------------------- + Limit + -> Sort + Sort Key: d.c2 + -> Hash Join + Hash Cond: (d.c8 = e.c1) + -> Foreign Scan on f_test_tbl1 d + Foreign Namespace: mongo_fdw_regress.test_tbl1 + -> Hash + -> HashAggregate + Group Key: e.c1 + -> Foreign Scan on f_test_tbl2 e + Foreign Namespace: mongo_fdw_regress.test_tbl2 +(12 rows) + +SELECT d.c2 + FROM f_test_tbl1 d WHERE EXISTS (SELECT 1 FROM f_test_tbl2 e WHERE d.c8 = e.c1) ORDER BY d.c2 LIMIT 10; + c2 +------- + EMP1 + EMP10 + EMP11 + EMP12 + EMP13 + EMP14 + EMP2 + EMP3 + EMP4 + EMP5 +(10 rows) + +-- ANTI JOIN, not pushed down +EXPLAIN (COSTS OFF) +SELECT d.c2 + FROM f_test_tbl1 d WHERE NOT EXISTS (SELECT 1 FROM f_test_tbl2 e WHERE d.c8 = e.c1) ORDER BY d.c2 LIMIT 10; + QUERY PLAN +-------------------------------------------------------------------------- + Limit + -> Sort + Sort Key: d.c2 + -> Hash Anti Join + Hash Cond: (d.c8 = e.c1) + -> Foreign Scan on f_test_tbl1 d + Foreign Namespace: mongo_fdw_regress.test_tbl1 + -> Hash + -> Foreign Scan on f_test_tbl2 e + Foreign Namespace: mongo_fdw_regress.test_tbl2 +(10 rows) + +SELECT d.c2 + FROM f_test_tbl1 d WHERE NOT EXISTS (SELECT 1 FROM f_test_tbl2 e WHERE d.c8 = e.c1) ORDER BY d.c2 LIMIT 10; + c2 +------- + EMP15 + EMP16 +(2 rows) + +-- FULL OUTER JOIN, should not pushdown. +EXPLAIN (COSTS OFF) +SELECT d.c1, e.c1 + FROM f_test_tbl1 d FULL JOIN f_test_tbl2 e ON (d.c8 = e.c1) ORDER BY d.c2 LIMIT 10; + QUERY PLAN +-------------------------------------------------------------------------- + Limit + -> Sort + Sort Key: d.c2 + -> Hash Full Join + Hash Cond: (d.c8 = e.c1) + -> Foreign Scan on f_test_tbl1 d + Foreign Namespace: mongo_fdw_regress.test_tbl1 + -> Hash + -> Foreign Scan on f_test_tbl2 e + Foreign Namespace: mongo_fdw_regress.test_tbl2 +(10 rows) + +SELECT d.c1, e.c1 + FROM f_test_tbl1 d FULL JOIN f_test_tbl2 e ON (d.c8 = e.c1) ORDER BY d.c2 LIMIT 10; + c1 | c1 +------+---- + 100 | 20 + 1000 | 30 + 1100 | 20 + 1200 | 30 + 1300 | 20 + 1400 | 10 + 1500 | + 1600 | + 200 | 30 + 300 | 30 +(10 rows) + +-- CROSS JOIN can be pushed down +EXPLAIN (COSTS OFF) +SELECT e.c1, d.c2 + FROM f_test_tbl1 d CROSS JOIN f_test_tbl2 e ORDER BY e.c1, d.c2 LIMIT 10; + QUERY PLAN +------------------------------------------------------------------------------------------------------------- + Limit + -> Sort + Sort Key: e.c1, d.c2 + -> Foreign Scan + Foreign Namespace: (mongo_fdw_regress.test_tbl1 d) INNER JOIN (mongo_fdw_regress.test_tbl2 e) +(5 rows) + +SELECT e.c1, d.c2 + FROM f_test_tbl1 d CROSS JOIN f_test_tbl2 e ORDER BY e.c1, d.c2 LIMIT 10; + c1 | c2 +----+------- + 10 | EMP1 + 10 | EMP10 + 10 | EMP11 + 10 | EMP12 + 10 | EMP13 + 10 | EMP14 + 10 | EMP15 + 10 | EMP16 + 10 | EMP2 + 10 | EMP3 +(10 rows) + +-- FDW-131: Limit and offset pushdown with join pushdown. +EXPLAIN (COSTS false, VERBOSE) +SELECT t1.c1, t2.c1 + FROM f_test_tbl1 t1 JOIN f_test_tbl2 t2 ON (TRUE) ORDER BY t1.c1 ASC NULLS FIRST, t2.c1 ASC NULLS FIRST LIMIT round(2.2) OFFSET 2; + QUERY PLAN +--------------------------------------------------------------------------------------------------- + Foreign Scan + Output: t1.c1, t2.c1 + Foreign Namespace: (mongo_fdw_regress.test_tbl1 t1) INNER JOIN (mongo_fdw_regress.test_tbl2 t2) +(3 rows) + +SELECT t1.c1, t2.c1 + FROM f_test_tbl1 t1 JOIN f_test_tbl2 t2 ON (TRUE) ORDER BY t1.c1 ASC NULLS FIRST, t2.c1 ASC NULLS FIRST LIMIT round(2.2) OFFSET 2; + c1 | c1 +-----+---- + 100 | 10 + 100 | 30 +(2 rows) + +-- Limit as NULL, no LIMIT/OFFSET pushdown. +EXPLAIN (COSTS false, VERBOSE) +SELECT t1.c1, t2.c1 + FROM f_test_tbl1 t1 JOIN f_test_tbl2 t2 ON (t1.c8 = t2.c1) ORDER BY t1.c1 ASC NULLS FIRST, t2.c1 ASC NULLS FIRST LIMIT NULL OFFSET 1; + QUERY PLAN +--------------------------------------------------------------------------------------------------- + Foreign Scan + Output: t1.c1, t2.c1 + Foreign Namespace: (mongo_fdw_regress.test_tbl1 t1) INNER JOIN (mongo_fdw_regress.test_tbl2 t2) +(3 rows) + +SELECT t1.c1, t2.c1 + FROM f_test_tbl1 t1 JOIN f_test_tbl2 t2 ON (t1.c8 = t2.c1) ORDER BY t1.c1 ASC NULLS FIRST, t2.c1 ASC NULLS FIRST LIMIT NULL OFFSET 1; + c1 | c1 +------+---- + 200 | 30 + 300 | 30 + 400 | 20 + 500 | 30 + 600 | 30 + 700 | 10 + 800 | 20 + 900 | 10 + 1000 | 30 + 1100 | 20 + 1200 | 30 + 1300 | 20 + 1400 | 10 +(13 rows) + +-- Limit as ALL, no LIMIT/OFFSET pushdown. +EXPLAIN (COSTS false, VERBOSE) +SELECT t1.c1, t2.c1 + FROM f_test_tbl1 t1 JOIN f_test_tbl2 t2 ON (t1.c8 = t2.c1) ORDER BY t1.c1 ASC NULLS FIRST, t2.c1 ASC NULLS FIRST LIMIT ALL OFFSET 1; + QUERY PLAN +--------------------------------------------------------------------------------------------------- + Foreign Scan + Output: t1.c1, t2.c1 + Foreign Namespace: (mongo_fdw_regress.test_tbl1 t1) INNER JOIN (mongo_fdw_regress.test_tbl2 t2) +(3 rows) + +SELECT t1.c1, t2.c1 + FROM f_test_tbl1 t1 JOIN f_test_tbl2 t2 ON (t1.c8 = t2.c1) ORDER BY t1.c1 ASC NULLS FIRST, t2.c1 ASC NULLS FIRST LIMIT ALL OFFSET 1; + c1 | c1 +------+---- + 200 | 30 + 300 | 30 + 400 | 20 + 500 | 30 + 600 | 30 + 700 | 10 + 800 | 20 + 900 | 10 + 1000 | 30 + 1100 | 20 + 1200 | 30 + 1300 | 20 + 1400 | 10 +(13 rows) + +-- Offset as NULL, no LIMIT/OFFSET pushdown. +EXPLAIN (COSTS false, VERBOSE) +SELECT t1.c1, t2.c1 + FROM f_test_tbl1 t1 JOIN f_test_tbl2 t2 ON (TRUE) ORDER BY t1.c1 ASC NULLS FIRST, t2.c1 ASC NULLS FIRST LIMIT 3 OFFSET NULL; + QUERY PLAN +--------------------------------------------------------------------------------------------------- + Foreign Scan + Output: t1.c1, t2.c1 + Foreign Namespace: (mongo_fdw_regress.test_tbl1 t1) INNER JOIN (mongo_fdw_regress.test_tbl2 t2) +(3 rows) + +SELECT t1.c1, t2.c1 + FROM f_test_tbl1 t1 JOIN f_test_tbl2 t2 ON (TRUE) ORDER BY t1.c1 ASC NULLS FIRST, t2.c1 ASC NULLS FIRST LIMIT 3 OFFSET NULL; + c1 | c1 +-----+---- + 100 | 10 + 100 | 20 + 100 | 30 +(3 rows) + +-- Limit with -ve value. Shouldn't pushdown. +EXPLAIN (COSTS false, VERBOSE) +SELECT t1.c1, t2.c1 + FROM f_test_tbl1 t1 JOIN f_test_tbl2 t2 ON (TRUE) ORDER BY t1.c1 ASC NULLS FIRST, t2.c1 ASC NULLS FIRST LIMIT -2; + QUERY PLAN +--------------------------------------------------------------------------------------------------------- + Limit + Output: t1.c1, t2.c1 + -> Foreign Scan + Output: t1.c1, t2.c1 + Foreign Namespace: (mongo_fdw_regress.test_tbl1 t1) INNER JOIN (mongo_fdw_regress.test_tbl2 t2) +(5 rows) + +-- Should throw an error. +SELECT t1.c1, t2.c1 + FROM f_test_tbl1 t1 JOIN f_test_tbl2 t2 ON (TRUE) ORDER BY t1.c1 ASC NULLS FIRST, t2.c1 ASC NULLS FIRST LIMIT -2; +ERROR: LIMIT must not be negative +-- Offset with -ve value. Shouldn't pushdown. +EXPLAIN (COSTS false, VERBOSE) +SELECT t1.c1, t2.c1 + FROM f_test_tbl1 t1 JOIN f_test_tbl2 t2 ON (TRUE) ORDER BY t1.c1 ASC NULLS FIRST, t2.c1 ASC NULLS FIRST OFFSET -1; + QUERY PLAN +--------------------------------------------------------------------------------------------------------- + Limit + Output: t1.c1, t2.c1 + -> Foreign Scan + Output: t1.c1, t2.c1 + Foreign Namespace: (mongo_fdw_regress.test_tbl1 t1) INNER JOIN (mongo_fdw_regress.test_tbl2 t2) +(5 rows) + +-- Should throw an error. +SELECT t1.c1, t2.c1 + FROM f_test_tbl1 t1 JOIN f_test_tbl2 t2 ON (TRUE) ORDER BY t1.c1 ASC NULLS FIRST, t2.c1 ASC NULLS FIRST OFFSET -1; +ERROR: OFFSET must not be negative +-- Limit/Offset with -ve value. Shouldn't pushdown. +EXPLAIN (COSTS false, VERBOSE) +SELECT t1.c1, t2.c1 + FROM f_test_tbl1 t1 JOIN f_test_tbl2 t2 ON (TRUE) ORDER BY t1.c1 ASC NULLS FIRST, t2.c1 ASC NULLS FIRST LIMIT -3 OFFSET -1; + QUERY PLAN +--------------------------------------------------------------------------------------------------------- + Limit + Output: t1.c1, t2.c1 + -> Foreign Scan + Output: t1.c1, t2.c1 + Foreign Namespace: (mongo_fdw_regress.test_tbl1 t1) INNER JOIN (mongo_fdw_regress.test_tbl2 t2) +(5 rows) + +-- Should throw an error. +SELECT t1.c1, t2.c1 + FROM f_test_tbl1 t1 JOIN f_test_tbl2 t2 ON (TRUE) ORDER BY t1.c1 ASC NULLS FIRST, t2.c1 ASC NULLS FIRST LIMIT -3 OFFSET -1; +ERROR: OFFSET must not be negative +-- Limit with expression evaluating to -ve value. +EXPLAIN (COSTS false, VERBOSE) +SELECT t1.c1, t2.c1 + FROM f_test_tbl1 t1 JOIN f_test_tbl2 t2 ON (TRUE) ORDER BY t1.c1 ASC NULLS FIRST, t2.c1 ASC NULLS FIRST LIMIT (1 - (SELECT COUNT(*) FROM f_test_tbl1)); + QUERY PLAN +--------------------------------------------------------------------------------------------------------- + Limit + Output: t1.c1, t2.c1 + InitPlan 1 + -> Foreign Scan + Output: (count(*)) + Foreign Namespace: Aggregate on (mongo_fdw_regress.test_tbl1 f_test_tbl1) + -> Foreign Scan + Output: t1.c1, t2.c1 + Foreign Namespace: (mongo_fdw_regress.test_tbl1 t1) INNER JOIN (mongo_fdw_regress.test_tbl2 t2) +(9 rows) + +-- Should throw an error. +SELECT t1.c1, t2.c1 + FROM f_test_tbl1 t1 JOIN f_test_tbl2 t2 ON (TRUE) ORDER BY t1.c1 ASC NULLS FIRST, t2.c1 ASC NULLS FIRST LIMIT (1 - (SELECT COUNT(*) FROM f_test_tbl1)); +ERROR: LIMIT must not be negative +-- Test partition-wise join +SET enable_partitionwise_join TO on; +-- Create the partition tables +CREATE TABLE fprt1 (_id NAME, c1 INTEGER, c2 INTEGER, c3 TEXT) PARTITION BY RANGE(c1); +CREATE FOREIGN TABLE ftprt1_p1 PARTITION OF fprt1 FOR VALUES FROM (1) TO (4) + SERVER mongo_server OPTIONS (database 'mongo_fdw_regress', collection 'test1'); +CREATE FOREIGN TABLE ftprt1_p2 PARTITION OF fprt1 FOR VALUES FROM (5) TO (8) + SERVER mongo_server OPTIONS (database 'mongo_fdw_regress', collection 'test2'); +CREATE TABLE fprt2 (_id NAME, c1 INTEGER, c2 INTEGER, c3 TEXT) PARTITION BY RANGE(c2); +CREATE FOREIGN TABLE ftprt2_p1 PARTITION OF fprt2 FOR VALUES FROM (1) TO (4) + SERVER mongo_server OPTIONS (database 'mongo_fdw_regress', collection 'test3'); +CREATE FOREIGN TABLE ftprt2_p2 PARTITION OF fprt2 FOR VALUES FROM (5) TO (8) + SERVER mongo_server OPTIONS (database 'mongo_fdw_regress', collection 'test4'); +-- Inner join two tables +-- Different explain plan on v10 as partition-wise join is not supported there. +SET enable_mergejoin TO OFF; +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.c1, t2.c2 + FROM fprt1 t1 INNER JOIN fprt2 t2 ON (t1.c1 = t2.c2) ORDER BY 1,2; + QUERY PLAN +------------------------------------------------------------------------------------------------------- + Sort + Output: t1.c1, t2.c2 + Sort Key: t1.c1 + -> Append + -> Foreign Scan + Output: t1_1.c1, t2_1.c2 + Foreign Namespace: (mongo_fdw_regress.test1 t1) INNER JOIN (mongo_fdw_regress.test3 t2) + -> Foreign Scan + Output: t1_2.c1, t2_2.c2 + Foreign Namespace: (mongo_fdw_regress.test2 t1) INNER JOIN (mongo_fdw_regress.test4 t2) +(10 rows) + +SELECT t1.c1, t2.c2 + FROM fprt1 t1 INNER JOIN fprt2 t2 ON (t1.c1 = t2.c2) ORDER BY 1,2; + c1 | c2 +----+---- + 1 | 1 + 2 | 2 + 3 | 3 + 4 | 4 + 5 | 5 + 6 | 6 + 7 | 7 + 8 | 8 +(8 rows) + +-- Inner join three tables +-- Different explain plan on v10 as partition-wise join is not supported there. +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.c1, t2.c2, t3.c2 + FROM fprt1 t1 INNER JOIN fprt2 t2 ON (t1.c1 = t2.c2) INNER JOIN fprt1 t3 ON (t3.c1 = t2.c2) ORDER BY 1,2; + QUERY PLAN +------------------------------------------------------------------------------------------------------------- + Sort + Output: t1.c1, t2.c2, t3.c2 + Sort Key: t1.c1 + -> Append + -> Hash Join + Output: t1_1.c1, t2_1.c2, t3_1.c2 + Hash Cond: (t1_1.c1 = t3_1.c1) + -> Foreign Scan + Output: t1_1.c1, t2_1.c2 + Foreign Namespace: (mongo_fdw_regress.test1 t1) INNER JOIN (mongo_fdw_regress.test3 t2) + -> Hash + Output: t3_1.c2, t3_1.c1 + -> Foreign Scan on public.ftprt1_p1 t3_1 + Output: t3_1.c2, t3_1.c1 + Foreign Namespace: mongo_fdw_regress.test1 + -> Hash Join + Output: t1_2.c1, t2_2.c2, t3_2.c2 + Hash Cond: (t1_2.c1 = t3_2.c1) + -> Foreign Scan + Output: t1_2.c1, t2_2.c2 + Foreign Namespace: (mongo_fdw_regress.test2 t1) INNER JOIN (mongo_fdw_regress.test4 t2) + -> Hash + Output: t3_2.c2, t3_2.c1 + -> Foreign Scan on public.ftprt1_p2 t3_2 + Output: t3_2.c2, t3_2.c1 + Foreign Namespace: mongo_fdw_regress.test2 +(26 rows) + +SELECT t1.c1, t2.c2, t3.c2 + FROM fprt1 t1 INNER JOIN fprt2 t2 ON (t1.c1 = t2.c2) INNER JOIN fprt1 t3 ON (t3.c1 = t2.c2) ORDER BY 1,2; + c1 | c2 | c2 +----+----+---- + 1 | 1 | 1 + 2 | 2 | 2 + 3 | 3 | 3 + 4 | 4 | 4 + 5 | 5 | 5 + 6 | 6 | 6 + 7 | 7 | 7 + 8 | 8 | 8 +(8 rows) + +RESET enable_mergejoin; +-- Join with lateral reference +-- Different explain plan on v10 as partition-wise join is not supported there. +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.c1, t1.c2 + FROM fprt1 t1, LATERAL (SELECT t2.c1, t2.c2 FROM fprt2 t2 + WHERE t1.c1 = t2.c2 AND t1.c2 = t2.c1) q WHERE t1.c1 % 2 = 0 ORDER BY 1,2; + QUERY PLAN +------------------------------------------------------------------------------------------------------- + Sort + Output: t1.c1, t1.c2 + Sort Key: t1.c1, t1.c2 + -> Append + -> Foreign Scan + Output: t1_1.c1, t1_1.c2 + Foreign Namespace: (mongo_fdw_regress.test1 t1) INNER JOIN (mongo_fdw_regress.test3 t2) + -> Foreign Scan + Output: t1_2.c1, t1_2.c2 + Foreign Namespace: (mongo_fdw_regress.test2 t1) INNER JOIN (mongo_fdw_regress.test4 t2) +(10 rows) + +SELECT t1.c1, t1.c2 + FROM fprt1 t1, LATERAL (SELECT t2.c1, t2.c2 FROM fprt2 t2 + WHERE t1.c1 = t2.c2 AND t1.c2 = t2.c1) q WHERE t1.c1 % 2 = 0 ORDER BY 1,2; + c1 | c2 +----+---- + 2 | 2 + 4 | 4 + 6 | 6 + 8 | 8 +(4 rows) + +-- With PHVs, partitionwise join selected but no join pushdown +-- Table alias in foreign scan is different for v12, v11 and v10. +EXPLAIN (VERBOSE, COSTS OFF) +SELECT t1.c1, t1.phv, t2.c2, t2.phv + FROM (SELECT 't1_phv' phv, * FROM fprt1 WHERE c1 % 2 = 0) t1 LEFT JOIN + (SELECT 't2_phv' phv, * FROM fprt2 WHERE c2 % 2 = 0) t2 ON (t1.c1 = t2.c2) + ORDER BY t1.c1, t2.c2; + QUERY PLAN +-------------------------------------------------------------------------------- + Incremental Sort + Output: fprt1.c1, 't1_phv'::text, fprt2.c2, ('t2_phv'::text) + Sort Key: fprt1.c1, fprt2.c2 + Presorted Key: fprt1.c1 + -> Merge Append + Sort Key: fprt1.c1 + -> Merge Left Join + Output: fprt1_1.c1, 't1_phv'::text, fprt2_1.c2, ('t2_phv'::text) + Merge Cond: (fprt1_1.c1 = fprt2_1.c2) + -> Sort + Output: fprt1_1.c1 + Sort Key: fprt1_1.c1 + -> Foreign Scan on public.ftprt1_p1 fprt1_1 + Output: fprt1_1.c1 + Foreign Namespace: mongo_fdw_regress.test1 + -> Sort + Output: fprt2_1.c2, ('t2_phv'::text) + Sort Key: fprt2_1.c2 + -> Foreign Scan on public.ftprt2_p1 fprt2_1 + Output: fprt2_1.c2, 't2_phv'::text + Foreign Namespace: mongo_fdw_regress.test3 + -> Merge Left Join + Output: fprt1_2.c1, 't1_phv'::text, fprt2_2.c2, ('t2_phv'::text) + Merge Cond: (fprt1_2.c1 = fprt2_2.c2) + -> Sort + Output: fprt1_2.c1 + Sort Key: fprt1_2.c1 + -> Foreign Scan on public.ftprt1_p2 fprt1_2 + Output: fprt1_2.c1 + Foreign Namespace: mongo_fdw_regress.test2 + -> Sort + Output: fprt2_2.c2, ('t2_phv'::text) + Sort Key: fprt2_2.c2 + -> Foreign Scan on public.ftprt2_p2 fprt2_2 + Output: fprt2_2.c2, 't2_phv'::text + Foreign Namespace: mongo_fdw_regress.test4 +(36 rows) + +SELECT t1.c1, t1.phv, t2.c2, t2.phv + FROM (SELECT 't1_phv' phv, * FROM fprt1 WHERE c1 % 2 = 0) t1 LEFT JOIN + (SELECT 't2_phv' phv, * FROM fprt2 WHERE c2 % 2 = 0) t2 ON (t1.c1 = t2.c2) + ORDER BY t1.c1, t2.c2; + c1 | phv | c2 | phv +----+--------+----+-------- + 2 | t1_phv | 2 | t2_phv + 4 | t1_phv | 4 | t2_phv + 6 | t1_phv | 6 | t2_phv + 8 | t1_phv | 8 | t2_phv +(4 rows) + +RESET enable_partitionwise_join; +-- FDW-445: Support enable_join_pushdown option at server level and table level. +-- Check only boolean values are accepted. +ALTER SERVER mongo_server OPTIONS (ADD enable_join_pushdown 'abc11'); +ERROR: enable_join_pushdown requires a Boolean value +-- Test the option at server level. +ALTER SERVER mongo_server OPTIONS (ADD enable_join_pushdown 'false'); +EXPLAIN (COSTS FALSE, VERBOSE) +SELECT d.c1, d.c2, e.c1, e.c2, e.c6, e.c8 + FROM f_test_tbl2 d JOIN f_test_tbl1 e ON d.c1 = e.c8 ORDER BY 1, 3; + QUERY PLAN +-------------------------------------------------------------------- + Incremental Sort + Output: d.c1, d.c2, e.c1, e.c2, e.c6, e.c8 + Sort Key: d.c1, e.c1 + Presorted Key: d.c1 + -> Merge Join + Output: d.c1, d.c2, e.c1, e.c2, e.c6, e.c8 + Merge Cond: (d.c1 = e.c8) + -> Sort + Output: d.c1, d.c2 + Sort Key: d.c1 + -> Foreign Scan on public.f_test_tbl2 d + Output: d.c1, d.c2 + Foreign Namespace: mongo_fdw_regress.test_tbl2 + -> Sort + Output: e.c1, e.c2, e.c6, e.c8 + Sort Key: e.c8 + -> Foreign Scan on public.f_test_tbl1 e + Output: e.c1, e.c2, e.c6, e.c8 + Foreign Namespace: mongo_fdw_regress.test_tbl1 +(19 rows) + +ALTER SERVER mongo_server OPTIONS (SET enable_join_pushdown 'true'); +EXPLAIN (COSTS FALSE, VERBOSE) +SELECT d.c1, d.c2, e.c1, e.c2, e.c6, e.c8 + FROM f_test_tbl2 d JOIN f_test_tbl1 e ON d.c1 = e.c8 ORDER BY 1, 3; + QUERY PLAN +------------------------------------------------------------------------------------------------------- + Sort + Output: d.c1, d.c2, e.c1, e.c2, e.c6, e.c8 + Sort Key: d.c1, e.c1 + -> Foreign Scan + Output: d.c1, d.c2, e.c1, e.c2, e.c6, e.c8 + Foreign Namespace: (mongo_fdw_regress.test_tbl2 d) INNER JOIN (mongo_fdw_regress.test_tbl1 e) +(6 rows) + +-- Test the option with outer rel. +ALTER FOREIGN TABLE f_test_tbl2 OPTIONS (ADD enable_join_pushdown 'false'); +EXPLAIN (COSTS FALSE, VERBOSE) +SELECT d.c1, d.c2, e.c1, e.c2, e.c6, e.c8 + FROM f_test_tbl2 d JOIN f_test_tbl1 e ON d.c1 = e.c8 ORDER BY 1, 3; + QUERY PLAN +-------------------------------------------------------------------- + Incremental Sort + Output: d.c1, d.c2, e.c1, e.c2, e.c6, e.c8 + Sort Key: d.c1, e.c1 + Presorted Key: d.c1 + -> Merge Join + Output: d.c1, d.c2, e.c1, e.c2, e.c6, e.c8 + Merge Cond: (d.c1 = e.c8) + -> Sort + Output: d.c1, d.c2 + Sort Key: d.c1 + -> Foreign Scan on public.f_test_tbl2 d + Output: d.c1, d.c2 + Foreign Namespace: mongo_fdw_regress.test_tbl2 + -> Sort + Output: e.c1, e.c2, e.c6, e.c8 + Sort Key: e.c8 + -> Foreign Scan on public.f_test_tbl1 e + Output: e.c1, e.c2, e.c6, e.c8 + Foreign Namespace: mongo_fdw_regress.test_tbl1 +(19 rows) + +ALTER FOREIGN TABLE f_test_tbl2 OPTIONS (SET enable_join_pushdown 'true'); +EXPLAIN (COSTS FALSE, VERBOSE) +SELECT d.c1, d.c2, e.c1, e.c2, e.c6, e.c8 + FROM f_test_tbl2 d JOIN f_test_tbl1 e ON d.c1 = e.c8 ORDER BY 1, 3; + QUERY PLAN +------------------------------------------------------------------------------------------------------- + Sort + Output: d.c1, d.c2, e.c1, e.c2, e.c6, e.c8 + Sort Key: d.c1, e.c1 + -> Foreign Scan + Output: d.c1, d.c2, e.c1, e.c2, e.c6, e.c8 + Foreign Namespace: (mongo_fdw_regress.test_tbl2 d) INNER JOIN (mongo_fdw_regress.test_tbl1 e) +(6 rows) + +-- Test the option with inner rel. +ALTER FOREIGN TABLE f_test_tbl1 OPTIONS (ADD enable_join_pushdown 'false'); +EXPLAIN (COSTS FALSE, VERBOSE) +SELECT d.c1, d.c2, e.c1, e.c2, e.c6, e.c8 + FROM f_test_tbl2 d JOIN f_test_tbl1 e ON d.c1 = e.c8 ORDER BY 1, 3; + QUERY PLAN +-------------------------------------------------------------------- + Incremental Sort + Output: d.c1, d.c2, e.c1, e.c2, e.c6, e.c8 + Sort Key: d.c1, e.c1 + Presorted Key: d.c1 + -> Merge Join + Output: d.c1, d.c2, e.c1, e.c2, e.c6, e.c8 + Merge Cond: (d.c1 = e.c8) + -> Sort + Output: d.c1, d.c2 + Sort Key: d.c1 + -> Foreign Scan on public.f_test_tbl2 d + Output: d.c1, d.c2 + Foreign Namespace: mongo_fdw_regress.test_tbl2 + -> Sort + Output: e.c1, e.c2, e.c6, e.c8 + Sort Key: e.c8 + -> Foreign Scan on public.f_test_tbl1 e + Output: e.c1, e.c2, e.c6, e.c8 + Foreign Namespace: mongo_fdw_regress.test_tbl1 +(19 rows) + +ALTER FOREIGN TABLE f_test_tbl1 OPTIONS (SET enable_join_pushdown 'true'); +EXPLAIN (COSTS FALSE, VERBOSE) +SELECT d.c1, d.c2, e.c1, e.c2, e.c6, e.c8 + FROM f_test_tbl2 d JOIN f_test_tbl1 e ON d.c1 = e.c8 ORDER BY 1, 3; + QUERY PLAN +------------------------------------------------------------------------------------------------------- + Sort + Output: d.c1, d.c2, e.c1, e.c2, e.c6, e.c8 + Sort Key: d.c1, e.c1 + -> Foreign Scan + Output: d.c1, d.c2, e.c1, e.c2, e.c6, e.c8 + Foreign Namespace: (mongo_fdw_regress.test_tbl2 d) INNER JOIN (mongo_fdw_regress.test_tbl1 e) +(6 rows) + +-- Test that setting option at table level does not affect the setting at +-- server level. +ALTER FOREIGN TABLE f_test_tbl1 OPTIONS (SET enable_join_pushdown 'false'); +ALTER FOREIGN TABLE f_test_tbl2 OPTIONS (SET enable_join_pushdown 'false'); +EXPLAIN (COSTS FALSE, VERBOSE) +SELECT d.c1, d.c2, e.c1, e.c2, e.c6, e.c8 + FROM f_test_tbl2 d JOIN f_test_tbl1 e ON d.c1 = e.c8 ORDER BY 1, 3; + QUERY PLAN +-------------------------------------------------------------------- + Incremental Sort + Output: d.c1, d.c2, e.c1, e.c2, e.c6, e.c8 + Sort Key: d.c1, e.c1 + Presorted Key: d.c1 + -> Merge Join + Output: d.c1, d.c2, e.c1, e.c2, e.c6, e.c8 + Merge Cond: (d.c1 = e.c8) + -> Sort + Output: d.c1, d.c2 + Sort Key: d.c1 + -> Foreign Scan on public.f_test_tbl2 d + Output: d.c1, d.c2 + Foreign Namespace: mongo_fdw_regress.test_tbl2 + -> Sort + Output: e.c1, e.c2, e.c6, e.c8 + Sort Key: e.c8 + -> Foreign Scan on public.f_test_tbl1 e + Output: e.c1, e.c2, e.c6, e.c8 + Foreign Namespace: mongo_fdw_regress.test_tbl1 +(19 rows) + +EXPLAIN (COSTS FALSE, VERBOSE) +SELECT t1.c1, t2.c2 + FROM f_test_tbl3 t1 JOIN f_test_tbl4 t2 ON (t1.c1 = t2.c8) ORDER BY 1, 2; + QUERY PLAN +--------------------------------------------------------------------------------------------------------- + Sort + Output: t1.c1, t2.c2 + Sort Key: t1.c1, t2.c2 + -> Foreign Scan + Output: t1.c1, t2.c2 + Foreign Namespace: (mongo_fdw_regress.test_tbl2 t1) INNER JOIN (mongo_fdw_regress.test_tbl1 t2) +(6 rows) + +-- FDW-558: Test mongo_fdw.enable_join_pushdown GUC. +-- Negative testing for GUC value. +SET mongo_fdw.enable_join_pushdown to 'abc'; +ERROR: parameter "mongo_fdw.enable_join_pushdown" requires a Boolean value +-- Check default value. Should be ON. +SHOW mongo_fdw.enable_join_pushdown; + mongo_fdw.enable_join_pushdown +-------------------------------- + on +(1 row) + +-- Join pushdown should happen as the GUC enable_join_pushdown is true. +ALTER SERVER mongo_server OPTIONS (SET enable_join_pushdown 'true'); +ALTER FOREIGN TABLE f_test_tbl1 OPTIONS (SET enable_join_pushdown 'true'); +ALTER FOREIGN TABLE f_test_tbl2 OPTIONS (SET enable_join_pushdown 'true'); +EXPLAIN (COSTS FALSE, VERBOSE) +SELECT d.c1, e.c8 + FROM f_test_tbl2 d JOIN f_test_tbl1 e ON (d.c1 = e.c8) ORDER BY 1, 2; + QUERY PLAN +------------------------------------------------------------------------------------------------------- + Sort + Output: d.c1, e.c8 + Sort Key: d.c1 + -> Foreign Scan + Output: d.c1, e.c8 + Foreign Namespace: (mongo_fdw_regress.test_tbl2 d) INNER JOIN (mongo_fdw_regress.test_tbl1 e) +(6 rows) + +--Disable the GUC enable_join_pushdown. +SET mongo_fdw.enable_join_pushdown to false; +-- Join pushdown shouldn't happen as the GUC enable_join_pushdown is false. +EXPLAIN (COSTS FALSE, VERBOSE) +SELECT d.c1, e.c8 + FROM f_test_tbl2 d JOIN f_test_tbl1 e ON (d.c1 = e.c8) ORDER BY 1, 2; + QUERY PLAN +-------------------------------------------------------------- + Merge Join + Output: d.c1, e.c8 + Merge Cond: (d.c1 = e.c8) + -> Sort + Output: d.c1 + Sort Key: d.c1 + -> Foreign Scan on public.f_test_tbl2 d + Output: d.c1 + Foreign Namespace: mongo_fdw_regress.test_tbl2 + -> Sort + Output: e.c8 + Sort Key: e.c8 + -> Foreign Scan on public.f_test_tbl1 e + Output: e.c8 + Foreign Namespace: mongo_fdw_regress.test_tbl1 +(15 rows) + +-- Enable the GUC and table level option is set to false, should not pushdown. +ALTER FOREIGN TABLE f_test_tbl1 OPTIONS (SET enable_join_pushdown 'false'); +ALTER FOREIGN TABLE f_test_tbl2 OPTIONS (SET enable_join_pushdown 'false'); +SET mongo_fdw.enable_join_pushdown to true; +EXPLAIN (COSTS FALSE, VERBOSE) +SELECT d.c1, e.c8 + FROM f_test_tbl2 d JOIN f_test_tbl1 e ON (d.c1 = e.c8) ORDER BY 1, 2; + QUERY PLAN +-------------------------------------------------------------- + Merge Join + Output: d.c1, e.c8 + Merge Cond: (d.c1 = e.c8) + -> Sort + Output: d.c1 + Sort Key: d.c1 + -> Foreign Scan on public.f_test_tbl2 d + Output: d.c1 + Foreign Namespace: mongo_fdw_regress.test_tbl2 + -> Sort + Output: e.c8 + Sort Key: e.c8 + -> Foreign Scan on public.f_test_tbl1 e + Output: e.c8 + Foreign Namespace: mongo_fdw_regress.test_tbl1 +(15 rows) + +-- FDW-589: Test enable_order_by_pushdown option at server and table level. +SET mongo_fdw.enable_join_pushdown to true; +SET mongo_fdw.enable_order_by_pushdown to true; +ALTER FOREIGN TABLE f_test_tbl1 OPTIONS (SET enable_join_pushdown 'true'); +ALTER FOREIGN TABLE f_test_tbl2 OPTIONS (SET enable_join_pushdown 'true'); +ALTER SERVER mongo_server OPTIONS (ADD enable_order_by_pushdown 'true'); +ALTER FOREIGN TABLE f_test_tbl1 OPTIONS (ADD enable_order_by_pushdown 'true'); +ALTER FOREIGN TABLE f_test_tbl2 OPTIONS (ADD enable_order_by_pushdown 'true'); +EXPLAIN (COSTS OFF) +SELECT d.c1, d.c2, e.c1, e.c2, e.c6, e.c8 + FROM f_test_tbl2 d LEFT OUTER JOIN f_test_tbl1 e ON (d.c1 = e.c8 AND e.c4 > d.c1 AND e.c2 < d.c3) ORDER BY 1 ASC NULLS FIRST, 3 ASC NULLS FIRST; + QUERY PLAN +------------------------------------------------------------------------------------------------ + Foreign Scan + Foreign Namespace: (mongo_fdw_regress.test_tbl2 d) LEFT JOIN (mongo_fdw_regress.test_tbl1 e) +(2 rows) + +SELECT d.c1, d.c2, e.c1, e.c2, e.c6, e.c8 + FROM f_test_tbl2 d LEFT OUTER JOIN f_test_tbl1 e ON (d.c1 = e.c8 AND e.c4 > d.c1 AND e.c2 < d.c3) ORDER BY 1 ASC NULLS FIRST, 3 ASC NULLS FIRST; + c1 | c2 | c1 | c2 | c6 | c8 +----+----------------+------+-------+---------+---- + | | | | | + 10 | DEVELOPMENT | 700 | EMP7 | 2450.34 | 10 + 10 | DEVELOPMENT | 1400 | EMP14 | 1300 | 10 + 20 | ADMINISTRATION | | | | + 30 | SALES | 200 | EMP2 | 1600 | 30 + 30 | SALES | 300 | EMP3 | 1250 | 30 + 30 | SALES | 500 | EMP5 | 1250.23 | 30 + 30 | SALES | 600 | EMP6 | 2850 | 30 + 30 | SALES | 1000 | EMP10 | 1500 | 30 + 30 | SALES | 1200 | EMP12 | 950 | 30 + 40 | HR | | | | + 50 | TESTING | | | | +(12 rows) + +-- One table level option is OFF. Shouldn't pushdown ORDER BY. +ALTER FOREIGN TABLE f_test_tbl1 OPTIONS (SET enable_order_by_pushdown 'true'); +ALTER FOREIGN TABLE f_test_tbl2 OPTIONS (SET enable_order_by_pushdown 'false'); +EXPLAIN (COSTS OFF) +SELECT d.c1, d.c2, e.c1, e.c2, e.c6, e.c8 + FROM f_test_tbl2 d LEFT OUTER JOIN f_test_tbl1 e ON (d.c1 = e.c8 AND e.c4 > d.c1 AND e.c2 < d.c3) ORDER BY 1 ASC NULLS FIRST, 3 ASC NULLS FIRST; + QUERY PLAN +------------------------------------------------------------------------------------------------------ + Sort + Sort Key: d.c1 NULLS FIRST, e.c1 NULLS FIRST + -> Foreign Scan + Foreign Namespace: (mongo_fdw_regress.test_tbl2 d) LEFT JOIN (mongo_fdw_regress.test_tbl1 e) +(4 rows) + +SELECT d.c1, d.c2, e.c1, e.c2, e.c6, e.c8 + FROM f_test_tbl2 d LEFT OUTER JOIN f_test_tbl1 e ON (d.c1 = e.c8 AND e.c4 > d.c1 AND e.c2 < d.c3) ORDER BY 1 ASC NULLS FIRST, 3 ASC NULLS FIRST; + c1 | c2 | c1 | c2 | c6 | c8 +----+----------------+------+-------+---------+---- + | | | | | + 10 | DEVELOPMENT | 700 | EMP7 | 2450.34 | 10 + 10 | DEVELOPMENT | 1400 | EMP14 | 1300 | 10 + 20 | ADMINISTRATION | | | | + 30 | SALES | 200 | EMP2 | 1600 | 30 + 30 | SALES | 300 | EMP3 | 1250 | 30 + 30 | SALES | 500 | EMP5 | 1250.23 | 30 + 30 | SALES | 600 | EMP6 | 2850 | 30 + 30 | SALES | 1000 | EMP10 | 1500 | 30 + 30 | SALES | 1200 | EMP12 | 950 | 30 + 40 | HR | | | | + 50 | TESTING | | | | +(12 rows) + +-- Test that setting option at table level does not affect the setting at +-- server level. +ALTER SERVER mongo_server OPTIONS (SET enable_order_by_pushdown 'false'); +ALTER FOREIGN TABLE f_test_tbl1 OPTIONS (SET enable_order_by_pushdown 'true'); +ALTER FOREIGN TABLE f_test_tbl2 OPTIONS (SET enable_order_by_pushdown 'true'); +EXPLAIN (COSTS OFF) +SELECT d.c1, d.c2, e.c1, e.c2, e.c6, e.c8 + FROM f_test_tbl2 d LEFT OUTER JOIN f_test_tbl1 e ON (d.c1 = e.c8 AND e.c4 > d.c1 AND e.c2 < d.c3) ORDER BY 1 ASC NULLS FIRST, 3 ASC NULLS FIRST; + QUERY PLAN +------------------------------------------------------------------------------------------------ + Foreign Scan + Foreign Namespace: (mongo_fdw_regress.test_tbl2 d) LEFT JOIN (mongo_fdw_regress.test_tbl1 e) +(2 rows) + +SELECT d.c1, d.c2, e.c1, e.c2, e.c6, e.c8 + FROM f_test_tbl2 d LEFT OUTER JOIN f_test_tbl1 e ON (d.c1 = e.c8 AND e.c4 > d.c1 AND e.c2 < d.c3) ORDER BY 1 ASC NULLS FIRST, 3 ASC NULLS FIRST; + c1 | c2 | c1 | c2 | c6 | c8 +----+----------------+------+-------+---------+---- + | | | | | + 10 | DEVELOPMENT | 700 | EMP7 | 2450.34 | 10 + 10 | DEVELOPMENT | 1400 | EMP14 | 1300 | 10 + 20 | ADMINISTRATION | | | | + 30 | SALES | 200 | EMP2 | 1600 | 30 + 30 | SALES | 300 | EMP3 | 1250 | 30 + 30 | SALES | 500 | EMP5 | 1250.23 | 30 + 30 | SALES | 600 | EMP6 | 2850 | 30 + 30 | SALES | 1000 | EMP10 | 1500 | 30 + 30 | SALES | 1200 | EMP12 | 950 | 30 + 40 | HR | | | | + 50 | TESTING | | | | +(12 rows) + +ALTER SERVER mongo_server OPTIONS (SET enable_order_by_pushdown 'true'); +-- When enable_join_pushdown option is disabled. Shouldn't pushdown join and +-- hence, ORDER BY too. +ALTER FOREIGN TABLE f_test_tbl1 OPTIONS (SET enable_join_pushdown 'false'); +ALTER FOREIGN TABLE f_test_tbl2 OPTIONS (SET enable_join_pushdown 'false'); +EXPLAIN (COSTS OFF) +SELECT d.c1, d.c2, e.c1, e.c2, e.c6, e.c8 + FROM f_test_tbl2 d LEFT OUTER JOIN f_test_tbl1 e ON (d.c1 = e.c8 AND e.c4 > d.c1 AND e.c2 < d.c3) ORDER BY 1 ASC NULLS FIRST, 3 ASC NULLS FIRST; + QUERY PLAN +-------------------------------------------------------------------- + Incremental Sort + Sort Key: d.c1 NULLS FIRST, e.c1 NULLS FIRST + Presorted Key: d.c1 + -> Merge Left Join + Merge Cond: (d.c1 = e.c8) + Join Filter: ((e.c4 > d.c1) AND (e.c2 < d.c3)) + -> Sort + Sort Key: d.c1 NULLS FIRST + -> Foreign Scan on f_test_tbl2 d + Foreign Namespace: mongo_fdw_regress.test_tbl2 + -> Sort + Sort Key: e.c8 NULLS FIRST + -> Foreign Scan on f_test_tbl1 e + Foreign Namespace: mongo_fdw_regress.test_tbl1 +(14 rows) + +SELECT d.c1, d.c2, e.c1, e.c2, e.c6, e.c8 + FROM f_test_tbl2 d LEFT OUTER JOIN f_test_tbl1 e ON (d.c1 = e.c8 AND e.c4 > d.c1 AND e.c2 < d.c3) ORDER BY 1 ASC NULLS FIRST, 3 ASC NULLS FIRST; + c1 | c2 | c1 | c2 | c6 | c8 +----+----------------+------+-------+---------+---- + | | | | | + 10 | DEVELOPMENT | 700 | EMP7 | 2450.34 | 10 + 10 | DEVELOPMENT | 1400 | EMP14 | 1300 | 10 + 20 | ADMINISTRATION | | | | + 30 | SALES | 200 | EMP2 | 1600 | 30 + 30 | SALES | 300 | EMP3 | 1250 | 30 + 30 | SALES | 500 | EMP5 | 1250.23 | 30 + 30 | SALES | 600 | EMP6 | 2850 | 30 + 30 | SALES | 1000 | EMP10 | 1500 | 30 + 30 | SALES | 1200 | EMP12 | 950 | 30 + 40 | HR | | | | + 50 | TESTING | | | | +(12 rows) + +DELETE FROM f_test_tbl1 WHERE c8 IS NULL; +DELETE FROM f_test_tbl1 WHERE c8 = 60; +DELETE FROM f_test_tbl2 WHERE c1 IS NULL; +DELETE FROM f_test_tbl2 WHERE c1 = 50; +DROP FOREIGN TABLE f_test_tbl1; +DROP FOREIGN TABLE f_test_tbl2; +DROP FOREIGN TABLE f_test_tbl3; +DROP FOREIGN TABLE f_test_tbl4; +DROP FOREIGN TABLE test_text; +DROP FOREIGN TABLE test_varchar; +DROP TABLE l_test_tbl1; +DROP FOREIGN TABLE ftprt1_p1; +DROP FOREIGN TABLE ftprt1_p2; +DROP FOREIGN TABLE ftprt2_p1; +DROP FOREIGN TABLE ftprt2_p2; +DROP TABLE IF EXISTS fprt1; +DROP TABLE IF EXISTS fprt2; +DROP USER MAPPING FOR public SERVER mongo_server1; +DROP SERVER mongo_server1; +DROP USER MAPPING FOR public SERVER mongo_server; +DROP SERVER mongo_server; +DROP EXTENSION mongo_fdw; diff --git a/expected/limit_offset_pushdown_1.out b/expected/limit_offset_pushdown_1.out new file mode 100644 index 0000000..e349f50 --- /dev/null +++ b/expected/limit_offset_pushdown_1.out @@ -0,0 +1,380 @@ +\set MONGO_HOST `echo \'"$MONGO_HOST"\'` +\set MONGO_PORT `echo \'"$MONGO_PORT"\'` +\set MONGO_USER_NAME `echo \'"$MONGO_USER_NAME"\'` +\set MONGO_PASS `echo \'"$MONGO_PWD"\'` +-- Before running this file user must create database mongo_fdw_regress, +-- mongo_fdw_regress1 and mongo_fdw_regress2 databases on MongoDB with all +-- permission for MONGO_USER_NAME user with MONGO_PASS password and ran +-- mongodb_init.sh file to load collections. +\c contrib_regression +CREATE EXTENSION IF NOT EXISTS mongo_fdw; +CREATE SERVER mongo_server FOREIGN DATA WRAPPER mongo_fdw + OPTIONS (address :MONGO_HOST, port :MONGO_PORT); +CREATE USER MAPPING FOR public SERVER mongo_server; +CREATE FOREIGN TABLE fdw131_t1 (_id NAME, c1 INTEGER, c2 TEXT, c3 TEXT) + SERVER mongo_server OPTIONS (database 'mongo_fdw_regress', collection 'test_tbl2'); +SELECT c1, c2, c3 FROM fdw131_t1 ORDER BY 1; + c1 | c2 | c3 +----+----------------+---------- + 10 | DEVELOPMENT | PUNE + 20 | ADMINISTRATION | BANGLORE + 30 | SALES | MUMBAI + 40 | HR | NAGPUR +(4 rows) + +-- LIMIT/OFFSET pushdown. +-- Limit with Offset should get pushdown. +EXPLAIN (VERBOSE, COSTS FALSE) +SELECT c1, c2, c3 FROM fdw131_t1 ORDER BY 1 ASC NULLS FIRST LIMIT 2 OFFSET 2; + QUERY PLAN +-------------------------------------------------- + Foreign Scan on public.fdw131_t1 + Output: c1, c2, c3 + Foreign Namespace: mongo_fdw_regress.test_tbl2 +(3 rows) + +SELECT c1, c2, c3 FROM fdw131_t1 ORDER BY 1 ASC NULLS FIRST LIMIT 2 OFFSET 2; + c1 | c2 | c3 +----+-------+-------- + 30 | SALES | MUMBAI + 40 | HR | NAGPUR +(2 rows) + +-- If ORDER BY is not pushable then limit/Offset shouldn't get pushdown. +EXPLAIN (VERBOSE, COSTS FALSE) +SELECT c1, c2, c3 FROM fdw131_t1 ORDER BY 1 LIMIT 2 OFFSET 2; + QUERY PLAN +-------------------------------------------------------------- + Limit + Output: c1, c2, c3 + -> Sort + Output: c1, c2, c3 + Sort Key: fdw131_t1.c1 + -> Foreign Scan on public.fdw131_t1 + Output: c1, c2, c3 + Foreign Namespace: mongo_fdw_regress.test_tbl2 +(8 rows) + +SELECT c1, c2, c3 FROM fdw131_t1 ORDER BY 1 LIMIT 2 OFFSET 2; + c1 | c2 | c3 +----+-------+-------- + 30 | SALES | MUMBAI + 40 | HR | NAGPUR +(2 rows) + +-- With ORDER BY pushdown disabled, limit shouldn't get pushdown. +SET mongo_fdw.enable_order_by_pushdown TO OFF; +EXPLAIN (VERBOSE, COSTS FALSE) +SELECT c1, c2, c3 FROM fdw131_t1 ORDER BY 1 ASC NULLS FIRST LIMIT 2 OFFSET 2; + QUERY PLAN +-------------------------------------------------------------- + Limit + Output: c1, c2, c3 + -> Sort + Output: c1, c2, c3 + Sort Key: fdw131_t1.c1 NULLS FIRST + -> Foreign Scan on public.fdw131_t1 + Output: c1, c2, c3 + Foreign Namespace: mongo_fdw_regress.test_tbl2 +(8 rows) + +SELECT c1, c2, c3 FROM fdw131_t1 ORDER BY 1 ASC NULLS FIRST LIMIT 2 OFFSET 2; + c1 | c2 | c3 +----+-------+-------- + 30 | SALES | MUMBAI + 40 | HR | NAGPUR +(2 rows) + +SET mongo_fdw.enable_order_by_pushdown TO ON; +-- Only limit should get pushdown. +EXPLAIN (VERBOSE, COSTS FALSE) +SELECT c1, c2, c3 FROM fdw131_t1 ORDER BY 2 DESC NULLS LAST LIMIT 3; + QUERY PLAN +-------------------------------------------------- + Foreign Scan on public.fdw131_t1 + Output: c1, c2, c3 + Foreign Namespace: mongo_fdw_regress.test_tbl2 +(3 rows) + +SELECT c1, c2, c3 FROM fdw131_t1 ORDER BY 2 DESC NULLS LAST LIMIT 3; + c1 | c2 | c3 +----+-------------+-------- + 30 | SALES | MUMBAI + 40 | HR | NAGPUR + 10 | DEVELOPMENT | PUNE +(3 rows) + +-- Expression in limit clause. Should get pushdown. +EXPLAIN (VERBOSE, COSTS FALSE) +SELECT c1, c2, c3 FROM fdw131_t1 ORDER BY 3 DESC NULLS LAST LIMIT round(3.2) OFFSET 2; + QUERY PLAN +-------------------------------------------------- + Foreign Scan on public.fdw131_t1 + Output: c1, c2, c3 + Foreign Namespace: mongo_fdw_regress.test_tbl2 +(3 rows) + +SELECT c1, c2, c3 FROM fdw131_t1 ORDER BY 3 DESC NULLS LAST LIMIT round(3.2) OFFSET 2; + c1 | c2 | c3 +----+----------------+---------- + 30 | SALES | MUMBAI + 20 | ADMINISTRATION | BANGLORE +(2 rows) + +-- Only Offset without limit should get pushdown. +EXPLAIN (VERBOSE, COSTS FALSE) +SELECT c1, c2, c3 FROM fdw131_t1 ORDER BY 3 ASC NULLS FIRST OFFSET 2; + QUERY PLAN +-------------------------------------------------- + Foreign Scan on public.fdw131_t1 + Output: c1, c2, c3 + Foreign Namespace: mongo_fdw_regress.test_tbl2 +(3 rows) + +SELECT c1, c2, c3 FROM fdw131_t1 ORDER BY 3 ASC NULLS FIRST OFFSET 2; + c1 | c2 | c3 +----+-------------+-------- + 40 | HR | NAGPUR + 10 | DEVELOPMENT | PUNE +(2 rows) + +-- Limit ALL +EXPLAIN (VERBOSE, COSTS FALSE) +SELECT c1, c2, c3 FROM fdw131_t1 ORDER BY 1 ASC NULLS FIRST LIMIT ALL; + QUERY PLAN +-------------------------------------------------- + Foreign Scan on public.fdw131_t1 + Output: c1, c2, c3 + Foreign Namespace: mongo_fdw_regress.test_tbl2 +(3 rows) + +SELECT c1, c2, c3 FROM fdw131_t1 ORDER BY 1 ASC NULLS FIRST LIMIT ALL; + c1 | c2 | c3 +----+----------------+---------- + 10 | DEVELOPMENT | PUNE + 20 | ADMINISTRATION | BANGLORE + 30 | SALES | MUMBAI + 40 | HR | NAGPUR +(4 rows) + +-- Limit ALL with OFFSET +EXPLAIN (VERBOSE, COSTS FALSE) +SELECT c1, c2, c3 FROM fdw131_t1 ORDER BY 1 ASC NULLS FIRST LIMIT ALL OFFSET 1; + QUERY PLAN +-------------------------------------------------- + Foreign Scan on public.fdw131_t1 + Output: c1, c2, c3 + Foreign Namespace: mongo_fdw_regress.test_tbl2 +(3 rows) + +SELECT c1, c2, c3 FROM fdw131_t1 ORDER BY 1 ASC NULLS FIRST LIMIT ALL OFFSET 1; + c1 | c2 | c3 +----+----------------+---------- + 20 | ADMINISTRATION | BANGLORE + 30 | SALES | MUMBAI + 40 | HR | NAGPUR +(3 rows) + +-- Limit NULL +EXPLAIN (VERBOSE, COSTS FALSE) +SELECT c1, c2, c3 FROM fdw131_t1 ORDER BY 3 ASC NULLS FIRST LIMIT NULL; + QUERY PLAN +-------------------------------------------------- + Foreign Scan on public.fdw131_t1 + Output: c1, c2, c3 + Foreign Namespace: mongo_fdw_regress.test_tbl2 +(3 rows) + +SELECT c1, c2, c3 FROM fdw131_t1 ORDER BY 3 ASC NULLS FIRST LIMIT NULL; + c1 | c2 | c3 +----+----------------+---------- + 20 | ADMINISTRATION | BANGLORE + 30 | SALES | MUMBAI + 40 | HR | NAGPUR + 10 | DEVELOPMENT | PUNE +(4 rows) + +EXPLAIN (VERBOSE, COSTS FALSE) +SELECT c1, c2, c3 FROM fdw131_t1 ORDER BY 3 ASC NULLS FIRST LIMIT NULL OFFSET 2; + QUERY PLAN +-------------------------------------------------- + Foreign Scan on public.fdw131_t1 + Output: c1, c2, c3 + Foreign Namespace: mongo_fdw_regress.test_tbl2 +(3 rows) + +SELECT c1, c2, c3 FROM fdw131_t1 ORDER BY 3 ASC NULLS FIRST LIMIT NULL OFFSET 2; + c1 | c2 | c3 +----+-------------+-------- + 40 | HR | NAGPUR + 10 | DEVELOPMENT | PUNE +(2 rows) + +-- Limit 0 and Offset 0 +EXPLAIN (VERBOSE, COSTS FALSE) +SELECT c1, c2, c3 FROM fdw131_t1 ORDER BY 1 ASC NULLS FIRST LIMIT 0; + QUERY PLAN +-------------------------------------------------- + Foreign Scan on public.fdw131_t1 + Output: c1, c2, c3 + Foreign Namespace: mongo_fdw_regress.test_tbl2 +(3 rows) + +SELECT c1, c2, c3 FROM fdw131_t1 ORDER BY 1 ASC NULLS FIRST LIMIT 0; + c1 | c2 | c3 +----+----+---- +(0 rows) + +EXPLAIN (VERBOSE, COSTS FALSE) +SELECT c1, c2, c3 FROM fdw131_t1 ORDER BY 1 ASC NULLS FIRST LIMIT 0 OFFSET 0; + QUERY PLAN +-------------------------------------------------- + Foreign Scan on public.fdw131_t1 + Output: c1, c2, c3 + Foreign Namespace: mongo_fdw_regress.test_tbl2 +(3 rows) + +SELECT c1, c2, c3 FROM fdw131_t1 ORDER BY 1 ASC NULLS FIRST LIMIT 0 OFFSET 0; + c1 | c2 | c3 +----+----+---- +(0 rows) + +-- Offset NULL. +EXPLAIN (VERBOSE, COSTS FALSE) +SELECT c1, c2, c3 FROM fdw131_t1 ORDER BY 2 ASC NULLS FIRST LIMIT 5 OFFSET NULL; + QUERY PLAN +-------------------------------------------------- + Foreign Scan on public.fdw131_t1 + Output: c1, c2, c3 + Foreign Namespace: mongo_fdw_regress.test_tbl2 +(3 rows) + +SELECT c1, c2, c3 FROM fdw131_t1 ORDER BY 2 ASC NULLS FIRST LIMIT 5 OFFSET NULL; + c1 | c2 | c3 +----+----------------+---------- + 20 | ADMINISTRATION | BANGLORE + 10 | DEVELOPMENT | PUNE + 40 | HR | NAGPUR + 30 | SALES | MUMBAI +(4 rows) + +-- Limit with placeholder. Shouldn't get pushdown. +EXPLAIN (VERBOSE, COSTS FALSE) +SELECT c1, c2, c3 FROM fdw131_t1 ORDER BY 2 LIMIT (SELECT COUNT(*) FROM fdw131_t1); + QUERY PLAN +----------------------------------------------------------------------------------- + Limit + Output: fdw131_t1.c1, fdw131_t1.c2, fdw131_t1.c3 + InitPlan 1 + -> Foreign Scan + Output: (count(*)) + Foreign Namespace: Aggregate on (mongo_fdw_regress.test_tbl2 fdw131_t1) + -> Sort + Output: fdw131_t1.c1, fdw131_t1.c2, fdw131_t1.c3 + Sort Key: fdw131_t1.c2 + -> Foreign Scan on public.fdw131_t1 + Output: fdw131_t1.c1, fdw131_t1.c2, fdw131_t1.c3 + Foreign Namespace: mongo_fdw_regress.test_tbl2 +(12 rows) + +SELECT c1, c2, c3 FROM fdw131_t1 ORDER BY 2 LIMIT (SELECT COUNT(*) FROM fdw131_t1); + c1 | c2 | c3 +----+----------------+---------- + 20 | ADMINISTRATION | BANGLORE + 10 | DEVELOPMENT | PUNE + 40 | HR | NAGPUR + 30 | SALES | MUMBAI +(4 rows) + +-- Limit with expression, shouldn't pushdown. +EXPLAIN (VERBOSE, COSTS FALSE) +SELECT c1, c2, c3 FROM fdw131_t1 ORDER BY 1 ASC NULLS FIRST LIMIT (10 - (SELECT COUNT(*) FROM fdw131_t1)); + QUERY PLAN +----------------------------------------------------------------------------------- + Limit + Output: fdw131_t1.c1, fdw131_t1.c2, fdw131_t1.c3 + InitPlan 1 + -> Foreign Scan + Output: (count(*)) + Foreign Namespace: Aggregate on (mongo_fdw_regress.test_tbl2 fdw131_t1) + -> Foreign Scan on public.fdw131_t1 + Output: fdw131_t1.c1, fdw131_t1.c2, fdw131_t1.c3 + Foreign Namespace: mongo_fdw_regress.test_tbl2 +(9 rows) + +SELECT c1, c2, c3 FROM fdw131_t1 ORDER BY 1 ASC NULLS FIRST LIMIT (10 - (SELECT COUNT(*) FROM fdw131_t1)); + c1 | c2 | c3 +----+----------------+---------- + 10 | DEVELOPMENT | PUNE + 20 | ADMINISTRATION | BANGLORE + 30 | SALES | MUMBAI + 40 | HR | NAGPUR +(4 rows) + +-- Limit with -ve value. Shouldn't pushdown. +EXPLAIN (VERBOSE, COSTS FALSE) +SELECT c1, c2, c3 FROM fdw131_t1 ORDER BY 1 ASC NULLS FIRST LIMIT -1; + QUERY PLAN +-------------------------------------------------------- + Limit + Output: c1, c2, c3 + -> Foreign Scan on public.fdw131_t1 + Output: c1, c2, c3 + Foreign Namespace: mongo_fdw_regress.test_tbl2 +(5 rows) + +-- Should throw an error. +SELECT c1, c2, c3 FROM fdw131_t1 ORDER BY 1 ASC NULLS FIRST LIMIT -1; +ERROR: LIMIT must not be negative +-- Offset with -ve value. Shouldn't pushdown. +EXPLAIN (VERBOSE, COSTS FALSE) +SELECT c1, c2, c3 FROM fdw131_t1 ORDER BY 1 ASC NULLS FIRST OFFSET -2; + QUERY PLAN +-------------------------------------------------------- + Limit + Output: c1, c2, c3 + -> Foreign Scan on public.fdw131_t1 + Output: c1, c2, c3 + Foreign Namespace: mongo_fdw_regress.test_tbl2 +(5 rows) + +-- Should throw an error. +SELECT c1, c2, c3 FROM fdw131_t1 ORDER BY 1 ASC NULLS FIRST OFFSET -2; +ERROR: OFFSET must not be negative +-- Limit/Offset with -ve value. Shouldn't pushdown. +EXPLAIN (VERBOSE, COSTS FALSE) +SELECT c1, c2, c3 FROM fdw131_t1 ORDER BY 1 ASC NULLS FIRST LIMIT -1 OFFSET -2; + QUERY PLAN +-------------------------------------------------------- + Limit + Output: c1, c2, c3 + -> Foreign Scan on public.fdw131_t1 + Output: c1, c2, c3 + Foreign Namespace: mongo_fdw_regress.test_tbl2 +(5 rows) + +-- Should throw an error. +SELECT c1, c2, c3 FROM fdw131_t1 ORDER BY 1 ASC NULLS FIRST LIMIT -1 OFFSET -2; +ERROR: OFFSET must not be negative +-- Limit with expression evaluating to -ve value. +EXPLAIN (VERBOSE, COSTS FALSE) +SELECT c1, c2, c3 FROM fdw131_t1 ORDER BY 1 ASC NULLS FIRST LIMIT (1 - (SELECT COUNT(*) FROM fdw131_t1)); + QUERY PLAN +----------------------------------------------------------------------------------- + Limit + Output: fdw131_t1.c1, fdw131_t1.c2, fdw131_t1.c3 + InitPlan 1 + -> Foreign Scan + Output: (count(*)) + Foreign Namespace: Aggregate on (mongo_fdw_regress.test_tbl2 fdw131_t1) + -> Foreign Scan on public.fdw131_t1 + Output: fdw131_t1.c1, fdw131_t1.c2, fdw131_t1.c3 + Foreign Namespace: mongo_fdw_regress.test_tbl2 +(9 rows) + +SELECT c1, c2, c3 FROM fdw131_t1 ORDER BY 1 ASC NULLS FIRST LIMIT (1 - (SELECT COUNT(*) FROM fdw131_t1)); +ERROR: LIMIT must not be negative +DROP FOREIGN TABLE fdw131_t1; +DROP USER MAPPING FOR public SERVER mongo_server; +DROP SERVER mongo_server; +DROP EXTENSION mongo_fdw; diff --git a/mongo_fdw.c b/mongo_fdw.c index c20fa5a..5e5d66b 100644 --- a/mongo_fdw.c +++ b/mongo_fdw.c @@ -228,11 +228,20 @@ static List *mongo_get_useful_ecs_for_relation(PlannerInfo *root, RelOptInfo *rel); static List *mongo_get_useful_pathkeys_for_relation(PlannerInfo *root, RelOptInfo *rel); +#if PG_VERSION_NUM >= 170000 +static void mongo_add_paths_with_pathkeys(PlannerInfo *root, + RelOptInfo *rel, + Path *epq_path, + Cost base_startup_cost, + Cost base_total_cost, + List *restrictlist); +#else static void mongo_add_paths_with_pathkeys(PlannerInfo *root, RelOptInfo *rel, Path *epq_path, Cost base_startup_cost, Cost base_total_cost); +#endif static EquivalenceMember *mongo_find_em_for_rel_target(PlannerInfo *root, EquivalenceClass *ec, RelOptInfo *rel); @@ -564,6 +573,7 @@ mongoGetForeignPaths(PlannerInfo *root, } /* Create a foreign path node */ +#if PG_VERSION_NUM >= 170000 foreignPath = (Path *) create_foreignscan_path(root, baserel, NULL, /* default pathtarget */ baserel->rows, @@ -572,13 +582,30 @@ mongoGetForeignPaths(PlannerInfo *root, NIL, /* no pathkeys */ baserel->lateral_relids, NULL, /* no extra plan */ - NULL); /* no fdw_private data */ + NIL, /* no fdw_restrictinfo list */ + NIL); /* no fdw_private data */ +#else + foreignPath = (Path *) create_foreignscan_path(root, baserel, + NULL, /* default pathtarget */ + baserel->rows, + startupCost, + totalCost, + NIL, /* no pathkeys */ + baserel->lateral_relids, + NULL, /* no extra plan */ + NIL); /* no fdw_private list */ +#endif /* Add foreign path as the only possible path */ add_path(baserel, foreignPath); /* Add paths with pathkeys */ +#if PG_VERSION_NUM >= 170000 + mongo_add_paths_with_pathkeys(root, baserel, NULL, startupCost, totalCost, + NIL); +#else mongo_add_paths_with_pathkeys(root, baserel, NULL, startupCost, totalCost); +#endif } /* @@ -2088,7 +2115,11 @@ fill_tuple_slot(const BSON *bsonDocument, const char *bsonDocumentKey, str = bsonAsJson(bsonDocument); result = cstring_to_text_with_len(str, strlen(str)); +#if PG_VERSION_NUM >= 170000 + lex = makeJsonLexContext(NULL, result, false); +#else lex = makeJsonLexContext(result, false); +#endif pg_parse_json(lex, &nullSemAction); columnValue = PointerGetDatum(result); @@ -2555,7 +2586,11 @@ column_value(BSON_ITERATOR *bsonIterator, Oid columnTypeId, bsonToJsonStringValue(buffer, bsonIterator, BSON_TYPE_ARRAY == type); result = cstring_to_text_with_len(buffer->data, buffer->len); +#if PG_VERSION_NUM >= 170000 + lex = makeJsonLexContext(NULL, result, false); +#else lex = makeJsonLexContext(result, false); +#endif pg_parse_json(lex, &nullSemAction); columnValue = PointerGetDatum(result); } @@ -2964,6 +2999,7 @@ mongoGetForeignJoinPaths(PlannerInfo *root, RelOptInfo *joinrel, * Create a new join path and add it to the joinrel which represents a * join between foreign tables. */ +#if PG_VERSION_NUM >= 170000 joinpath = create_foreign_join_path(root, joinrel, NULL, @@ -2973,14 +3009,32 @@ mongoGetForeignJoinPaths(PlannerInfo *root, RelOptInfo *joinrel, NIL, /* no pathkeys */ joinrel->lateral_relids, epq_path, - NULL); /* no fdw_private */ + extra->restrictlist, + NIL); /* no fdw_private */ +#else + joinpath = create_foreign_join_path(root, + joinrel, + NULL, + joinrel->rows, + startup_cost, + total_cost, + NIL, /* no pathkeys */ + joinrel->lateral_relids, + epq_path, + NIL); /* no fdw_private */ +#endif /* Add generated path into joinrel by add_path(). */ add_path(joinrel, (Path *) joinpath); /* Add paths with pathkeys */ +#if PG_VERSION_NUM >= 170000 + mongo_add_paths_with_pathkeys(root, joinrel, epq_path, startup_cost, + total_cost, extra->restrictlist); +#else mongo_add_paths_with_pathkeys(root, joinrel, epq_path, startup_cost, total_cost); +#endif /* XXX Consider parameterized paths for the join relation */ } @@ -3574,6 +3628,18 @@ mongo_add_foreign_grouping_paths(PlannerInfo *root, RelOptInfo *input_rel, #endif /* Create and add foreign path to the grouping relation. */ +#if PG_VERSION_NUM >= 170000 + grouppath = create_foreign_upper_path(root, + grouped_rel, + grouped_rel->reltarget, + num_groups, + startup_cost, + total_cost, + NIL, /* no pathkeys */ + NULL, + NIL, /* no fdw_restrictinfo list */ + NIL); /* no fdw_private */ +#else grouppath = create_foreign_upper_path(root, grouped_rel, grouped_rel->reltarget, @@ -3583,6 +3649,7 @@ mongo_add_foreign_grouping_paths(PlannerInfo *root, RelOptInfo *input_rel, NIL, /* no pathkeys */ NULL, NIL); /* no fdw_private */ +#endif /* Add generated path into grouped_rel by add_path(). */ add_path(grouped_rel, (Path *) grouppath); @@ -3861,10 +3928,17 @@ mongo_get_useful_pathkeys_for_relation(PlannerInfo *root, RelOptInfo *rel) * Pushing down query_pathkeys to the foreign server might let us avoid a * local sort. */ +#if PG_VERSION_NUM >= 170000 +static void +mongo_add_paths_with_pathkeys(PlannerInfo *root, RelOptInfo *rel, + Path *epq_path, Cost base_startup_cost, + Cost base_total_cost, List *restrictlist) +#else static void mongo_add_paths_with_pathkeys(PlannerInfo *root, RelOptInfo *rel, Path *epq_path, Cost base_startup_cost, Cost base_total_cost) +#endif { ListCell *lc; List *useful_pathkeys_list = NIL; /* List of all pathkeys */ @@ -3911,6 +3985,19 @@ mongo_add_paths_with_pathkeys(PlannerInfo *root, RelOptInfo *rel, -1.0); if (IS_SIMPLE_REL(rel)) +#if PG_VERSION_NUM >= 170000 + add_path(rel, (Path *) + create_foreignscan_path(root, rel, + NULL, + rel->rows, + startup_cost, + total_cost, + useful_pathkeys, + rel->lateral_relids, + sorted_epq_path, + NIL, /* no fdw_restrictinfo list */ + NIL)); /* no fdw_private list */ +#else add_path(rel, (Path *) create_foreignscan_path(root, rel, NULL, @@ -3920,8 +4007,10 @@ mongo_add_paths_with_pathkeys(PlannerInfo *root, RelOptInfo *rel, useful_pathkeys, rel->lateral_relids, sorted_epq_path, - NIL)); + NIL)); /* no fdw_private list */ +#endif else +#if PG_VERSION_NUM >= 170000 add_path(rel, (Path *) create_foreign_join_path(root, rel, NULL, @@ -3931,7 +4020,20 @@ mongo_add_paths_with_pathkeys(PlannerInfo *root, RelOptInfo *rel, useful_pathkeys, rel->lateral_relids, sorted_epq_path, - NIL)); + restrictlist, + NIL)); /* no fdw_private */ +#else + add_path(rel, (Path *) + create_foreign_join_path(root, rel, + NULL, + rel->rows, + startup_cost, + total_cost, + useful_pathkeys, + rel->lateral_relids, + sorted_epq_path, + NIL)); /* no fdw_private */ +#endif } } @@ -4098,6 +4200,7 @@ mongo_add_foreign_ordered_paths(PlannerInfo *root, RelOptInfo *input_rel, fdw_private = list_make2(makeInteger(true), makeInteger(false)); /* Create foreign ordering path */ +#if PG_VERSION_NUM >= 170000 ordered_path = create_foreign_upper_path(root, input_rel, root->upper_targets[UPPERREL_ORDERED], @@ -4106,7 +4209,19 @@ mongo_add_foreign_ordered_paths(PlannerInfo *root, RelOptInfo *input_rel, total_cost, root->sort_pathkeys, NULL, /* no extra plan */ + NIL, /* no fdw_restrictinfo list */ fdw_private); +#else + ordered_path = create_foreign_upper_path(root, + input_rel, + root->upper_targets[UPPERREL_ORDERED], + rows, + startup_cost, + total_cost, + root->sort_pathkeys, + NULL, /* no extra plan */ + fdw_private); +#endif /* and add it to the ordered_rel */ add_path(ordered_rel, (Path *) ordered_path); @@ -4201,6 +4316,18 @@ mongo_add_foreign_final_paths(PlannerInfo *root, RelOptInfo *input_rel, * no-longer-needed outer plan (if any), which makes the * EXPLAIN output look cleaner */ +#if PG_VERSION_NUM >= 170000 + final_path = create_foreign_upper_path(root, + path->parent, + path->pathtarget, + path->rows, + path->startup_cost, + path->total_cost, + path->pathkeys, + NULL, /* no extra plan */ + NIL, /* no fdw_restrictinfo list */ + NIL); /* no fdw_private */ +#else final_path = create_foreign_upper_path(root, path->parent, path->pathtarget, @@ -4209,7 +4336,8 @@ mongo_add_foreign_final_paths(PlannerInfo *root, RelOptInfo *input_rel, path->total_cost, path->pathkeys, NULL, /* no extra plan */ - NULL); /* no fdw_private */ + NIL); /* no fdw_private */ +#endif /* and add it to the final_rel */ add_path(final_rel, (Path *) final_path); @@ -4324,6 +4452,7 @@ mongo_add_foreign_final_paths(PlannerInfo *root, RelOptInfo *input_rel, * Create foreign final path; this gets rid of a no-longer-needed outer * plan (if any), which makes the EXPLAIN output look cleaner */ +#if PG_VERSION_NUM >= 170000 final_path = create_foreign_upper_path(root, input_rel, root->upper_targets[UPPERREL_FINAL], @@ -4332,7 +4461,19 @@ mongo_add_foreign_final_paths(PlannerInfo *root, RelOptInfo *input_rel, total_cost, pathkeys, NULL, /* no extra plan */ + NIL, /* no fdw_restrictinfo list */ fdw_private); +#else + final_path = create_foreign_upper_path(root, + input_rel, + root->upper_targets[UPPERREL_FINAL], + rows, + startup_cost, + total_cost, + pathkeys, + NULL, /* no extra plan */ + fdw_private); +#endif /* and add it to the final_rel */ add_path(final_rel, (Path *) final_path);