diff --git a/Makefile b/Makefile index 005dcce..3bbe05e 100644 --- a/Makefile +++ b/Makefile @@ -26,7 +26,7 @@ OBJS = connection.o option.o mongo_wrapper_meta.o mongo_fdw.o mongo_query.o depa EXTENSION = mongo_fdw DATA = mongo_fdw--1.0.sql mongo_fdw--1.1.sql mongo_fdw--1.0--1.1.sql -REGRESS = server_options connection_validation dml select pushdown join_pushdown aggregate_pushdown +REGRESS = server_options connection_validation dml select pushdown join_pushdown aggregate_pushdown limit_offset_pushdown REGRESS_OPTS = --load-extension=$(EXTENSION) # diff --git a/Makefile.meta b/Makefile.meta index 8bcc3f3..e98d28c 100644 --- a/Makefile.meta +++ b/Makefile.meta @@ -26,7 +26,7 @@ OBJS = connection.o option.o mongo_wrapper_meta.o mongo_fdw.o mongo_query.o depa EXTENSION = mongo_fdw DATA = mongo_fdw--1.0.sql mongo_fdw--1.1.sql mongo_fdw--1.0--1.1.sql -REGRESS = server_options connection_validation dml select pushdown join_pushdown aggregate_pushdown +REGRESS = server_options connection_validation dml select pushdown join_pushdown aggregate_pushdown limit_offset_pushdown REGRESS_OPTS = --load-extension=$(EXTENSION) # diff --git a/expected/aggregate_pushdown.out b/expected/aggregate_pushdown.out index 9281049..0dd754f 100644 --- a/expected/aggregate_pushdown.out +++ b/expected/aggregate_pushdown.out @@ -1436,6 +1436,155 @@ SELECT a32, sum(a32) FROM f_test_large GROUP BY 132 | 132 (3 rows) +-- FDW-131: Limit and offset pushdown with Aggregate pushdown. +SELECT min(c1), c1 FROM fdw137_t2 GROUP BY c1 ORDER BY c1; + min | c1 +-----+---- + 10 | 10 + 20 | 20 + 30 | 30 + 40 | 40 + 50 | 50 + | +(6 rows) + +EXPLAIN (VERBOSE, COSTS OFF) +SELECT min(c1), c1 FROM fdw137_t2 GROUP BY c1 ORDER BY c1 ASC NULLS FIRST LIMIT 1 OFFSET 1; + QUERY PLAN +--------------------------------------------------------------------------- + Foreign Scan + Output: (min(c1)), c1 + Foreign Namespace: Aggregate on (mongo_fdw_regress.test_tbl2 fdw137_t2) +(3 rows) + +SELECT min(c1), c1 FROM fdw137_t2 GROUP BY c1 ORDER BY c1 ASC NULLS FIRST LIMIT 1 OFFSET 1; + min | c1 +-----+---- + 10 | 10 +(1 row) + +-- Limit 0, Offset 0 with aggregates. +EXPLAIN (VERBOSE, COSTS OFF) +SELECT min(c1), c1 FROM fdw137_t2 GROUP BY c1 ORDER BY c1 ASC NULLS FIRST LIMIT 0 OFFSET 0; + QUERY PLAN +--------------------------------------------------------------------------- + Foreign Scan + Output: (min(c1)), c1 + Foreign Namespace: Aggregate on (mongo_fdw_regress.test_tbl2 fdw137_t2) +(3 rows) + +SELECT min(c1), c1 FROM fdw137_t2 GROUP BY c1 ORDER BY c1 ASC NULLS FIRST LIMIT 0 OFFSET 0; + min | c1 +-----+---- +(0 rows) + +-- Limit NULL +EXPLAIN (VERBOSE, COSTS OFF) +SELECT min(c1), c1 FROM fdw137_t2 GROUP BY c1 ORDER BY c1 ASC NULLS FIRST LIMIT NULL OFFSET 2; + QUERY PLAN +--------------------------------------------------------------------------- + Foreign Scan + Output: (min(c1)), c1 + Foreign Namespace: Aggregate on (mongo_fdw_regress.test_tbl2 fdw137_t2) +(3 rows) + +SELECT min(c1), c1 FROM fdw137_t2 GROUP BY c1 ORDER BY c1 ASC NULLS FIRST LIMIT NULL OFFSET 2; + min | c1 +-----+---- + 20 | 20 + 30 | 30 + 40 | 40 + 50 | 50 +(4 rows) + +-- Limit ALL +EXPLAIN (VERBOSE, COSTS OFF) +SELECT min(c1), c1 FROM fdw137_t2 GROUP BY c1 ORDER BY c1 ASC NULLS FIRST LIMIT ALL OFFSET 2; + QUERY PLAN +--------------------------------------------------------------------------- + Foreign Scan + Output: (min(c1)), c1 + Foreign Namespace: Aggregate on (mongo_fdw_regress.test_tbl2 fdw137_t2) +(3 rows) + +SELECT min(c1), c1 FROM fdw137_t2 GROUP BY c1 ORDER BY c1 ASC NULLS FIRST LIMIT ALL OFFSET 2; + min | c1 +-----+---- + 20 | 20 + 30 | 30 + 40 | 40 + 50 | 50 +(4 rows) + +-- Limit with -ve value. Shouldn't pushdown. +EXPLAIN (VERBOSE, COSTS FALSE) +SELECT c1, max(c1) FROM fdw137_t2 GROUP BY c1 ORDER BY 1 ASC NULLS FIRST LIMIT -1; + QUERY PLAN +-------------------------------------------------------------- + Limit + Output: c1, (max(c1)) + -> GroupAggregate + Output: c1, max(c1) + Group Key: fdw137_t2.c1 + -> Foreign Scan on public.fdw137_t2 + Output: _id, c1, c2, c3 + Foreign Namespace: mongo_fdw_regress.test_tbl2 +(8 rows) + +-- Should throw an error. +SELECT c1, max(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, max(c1) FROM fdw137_t2 GROUP BY c1 ORDER BY 1 ASC NULLS FIRST OFFSET -2; + QUERY PLAN +--------------------------------------------------------------------------------- + Limit + Output: c1, (max(c1)) + -> Foreign Scan + Output: c1, (max(c1)) + Foreign Namespace: Aggregate on (mongo_fdw_regress.test_tbl2 fdw137_t2) +(5 rows) + +-- Should throw an error. +SELECT c1, max(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)) + -> GroupAggregate + Output: c1, avg(c1) + Group Key: fdw137_t2.c1 + -> Foreign Scan on public.fdw137_t2 + Output: _id, c1, c2, c3 + Foreign Namespace: mongo_fdw_regress.test_tbl2 +(8 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 (returns $0) + -> 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 -- Cleanup DELETE FROM fdw137_t1 WHERE c8 IS NULL; DELETE FROM fdw137_t1 WHERE c8 = 60; diff --git a/expected/aggregate_pushdown_1.out b/expected/aggregate_pushdown_1.out index 2a13465..10c8016 100644 --- a/expected/aggregate_pushdown_1.out +++ b/expected/aggregate_pushdown_1.out @@ -1436,6 +1436,155 @@ SELECT a32, sum(a32) FROM f_test_large GROUP BY 132 | 132 (3 rows) +-- FDW-131: Limit and offset pushdown with Aggregate pushdown. +SELECT min(c1), c1 FROM fdw137_t2 GROUP BY c1 ORDER BY c1; + min | c1 +-----+---- + 10 | 10 + 20 | 20 + 30 | 30 + 40 | 40 + 50 | 50 + | +(6 rows) + +EXPLAIN (VERBOSE, COSTS OFF) +SELECT min(c1), c1 FROM fdw137_t2 GROUP BY c1 ORDER BY c1 ASC NULLS FIRST LIMIT 1 OFFSET 1; + QUERY PLAN +--------------------------------------------------------------------------- + Foreign Scan + Output: (min(c1)), c1 + Foreign Namespace: Aggregate on (mongo_fdw_regress.test_tbl2 fdw137_t2) +(3 rows) + +SELECT min(c1), c1 FROM fdw137_t2 GROUP BY c1 ORDER BY c1 ASC NULLS FIRST LIMIT 1 OFFSET 1; + min | c1 +-----+---- + 10 | 10 +(1 row) + +-- Limit 0, Offset 0 with aggregates. +EXPLAIN (VERBOSE, COSTS OFF) +SELECT min(c1), c1 FROM fdw137_t2 GROUP BY c1 ORDER BY c1 ASC NULLS FIRST LIMIT 0 OFFSET 0; + QUERY PLAN +--------------------------------------------------------------------------- + Foreign Scan + Output: (min(c1)), c1 + Foreign Namespace: Aggregate on (mongo_fdw_regress.test_tbl2 fdw137_t2) +(3 rows) + +SELECT min(c1), c1 FROM fdw137_t2 GROUP BY c1 ORDER BY c1 ASC NULLS FIRST LIMIT 0 OFFSET 0; + min | c1 +-----+---- +(0 rows) + +-- Limit NULL +EXPLAIN (VERBOSE, COSTS OFF) +SELECT min(c1), c1 FROM fdw137_t2 GROUP BY c1 ORDER BY c1 ASC NULLS FIRST LIMIT NULL OFFSET 2; + QUERY PLAN +--------------------------------------------------------------------------- + Foreign Scan + Output: (min(c1)), c1 + Foreign Namespace: Aggregate on (mongo_fdw_regress.test_tbl2 fdw137_t2) +(3 rows) + +SELECT min(c1), c1 FROM fdw137_t2 GROUP BY c1 ORDER BY c1 ASC NULLS FIRST LIMIT NULL OFFSET 2; + min | c1 +-----+---- + 20 | 20 + 30 | 30 + 40 | 40 + 50 | 50 +(4 rows) + +-- Limit ALL +EXPLAIN (VERBOSE, COSTS OFF) +SELECT min(c1), c1 FROM fdw137_t2 GROUP BY c1 ORDER BY c1 ASC NULLS FIRST LIMIT ALL OFFSET 2; + QUERY PLAN +--------------------------------------------------------------------------- + Foreign Scan + Output: (min(c1)), c1 + Foreign Namespace: Aggregate on (mongo_fdw_regress.test_tbl2 fdw137_t2) +(3 rows) + +SELECT min(c1), c1 FROM fdw137_t2 GROUP BY c1 ORDER BY c1 ASC NULLS FIRST LIMIT ALL OFFSET 2; + min | c1 +-----+---- + 20 | 20 + 30 | 30 + 40 | 40 + 50 | 50 +(4 rows) + +-- Limit with -ve value. Shouldn't pushdown. +EXPLAIN (VERBOSE, COSTS FALSE) +SELECT c1, max(c1) FROM fdw137_t2 GROUP BY c1 ORDER BY 1 ASC NULLS FIRST LIMIT -1; + QUERY PLAN +-------------------------------------------------------------- + Limit + Output: c1, (max(c1)) + -> GroupAggregate + Output: c1, max(c1) + Group Key: fdw137_t2.c1 + -> Foreign Scan on public.fdw137_t2 + Output: _id, c1, c2, c3 + Foreign Namespace: mongo_fdw_regress.test_tbl2 +(8 rows) + +-- Should throw an error. +SELECT c1, max(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, max(c1) FROM fdw137_t2 GROUP BY c1 ORDER BY 1 ASC NULLS FIRST OFFSET -2; + QUERY PLAN +--------------------------------------------------------------------------------- + Limit + Output: c1, (max(c1)) + -> Foreign Scan + Output: c1, (max(c1)) + Foreign Namespace: Aggregate on (mongo_fdw_regress.test_tbl2 fdw137_t2) +(5 rows) + +-- Should throw an error. +SELECT c1, max(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)) + -> GroupAggregate + Output: c1, avg(c1) + Group Key: fdw137_t2.c1 + -> Foreign Scan on public.fdw137_t2 + Output: _id, c1, c2, c3 + Foreign Namespace: mongo_fdw_regress.test_tbl2 +(8 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 (returns $0) + -> 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 -- Cleanup DELETE FROM fdw137_t1 WHERE c8 IS NULL; DELETE FROM fdw137_t1 WHERE c8 = 60; diff --git a/expected/aggregate_pushdown_2.out b/expected/aggregate_pushdown_2.out index 9f4955b..73bc84f 100644 --- a/expected/aggregate_pushdown_2.out +++ b/expected/aggregate_pushdown_2.out @@ -1459,6 +1459,181 @@ SELECT a32, sum(a32) FROM f_test_large GROUP BY 132 | 132 (3 rows) +-- FDW-131: Limit and offset pushdown with Aggregate pushdown. +SELECT min(c1), c1 FROM fdw137_t2 GROUP BY c1 ORDER BY c1; + min | c1 +-----+---- + 10 | 10 + 20 | 20 + 30 | 30 + 40 | 40 + 50 | 50 + | +(6 rows) + +EXPLAIN (VERBOSE, COSTS OFF) +SELECT min(c1), c1 FROM fdw137_t2 GROUP BY c1 ORDER BY c1 ASC NULLS FIRST LIMIT 1 OFFSET 1; + QUERY PLAN +-------------------------------------------------------------- + Limit + Output: (min(c1)), c1 + -> GroupAggregate + Output: min(c1), c1 + Group Key: fdw137_t2.c1 + -> Foreign Scan on public.fdw137_t2 + Output: _id, c1, c2, c3 + Foreign Namespace: mongo_fdw_regress.test_tbl2 +(8 rows) + +SELECT min(c1), c1 FROM fdw137_t2 GROUP BY c1 ORDER BY c1 ASC NULLS FIRST LIMIT 1 OFFSET 1; + min | c1 +-----+---- + 10 | 10 +(1 row) + +-- Limit 0, Offset 0 with aggregates. +EXPLAIN (VERBOSE, COSTS OFF) +SELECT min(c1), c1 FROM fdw137_t2 GROUP BY c1 ORDER BY c1 ASC NULLS FIRST LIMIT 0 OFFSET 0; + QUERY PLAN +-------------------------------------------------------------- + Limit + Output: (min(c1)), c1 + -> GroupAggregate + Output: min(c1), c1 + Group Key: fdw137_t2.c1 + -> Foreign Scan on public.fdw137_t2 + Output: _id, c1, c2, c3 + Foreign Namespace: mongo_fdw_regress.test_tbl2 +(8 rows) + +SELECT min(c1), c1 FROM fdw137_t2 GROUP BY c1 ORDER BY c1 ASC NULLS FIRST LIMIT 0 OFFSET 0; + min | c1 +-----+---- +(0 rows) + +-- Limit NULL +EXPLAIN (VERBOSE, COSTS OFF) +SELECT min(c1), c1 FROM fdw137_t2 GROUP BY c1 ORDER BY c1 ASC NULLS FIRST LIMIT NULL OFFSET 2; + QUERY PLAN +--------------------------------------------------------------------------------------- + Limit + Output: (min(c1)), c1 + -> Sort + Output: (min(c1)), c1 + Sort Key: fdw137_t2.c1 NULLS FIRST + -> Foreign Scan + Output: (min(c1)), c1 + Foreign Namespace: Aggregate on (mongo_fdw_regress.test_tbl2 fdw137_t2) +(8 rows) + +SELECT min(c1), c1 FROM fdw137_t2 GROUP BY c1 ORDER BY c1 ASC NULLS FIRST LIMIT NULL OFFSET 2; + min | c1 +-----+---- + 20 | 20 + 30 | 30 + 40 | 40 + 50 | 50 +(4 rows) + +-- Limit ALL +EXPLAIN (VERBOSE, COSTS OFF) +SELECT min(c1), c1 FROM fdw137_t2 GROUP BY c1 ORDER BY c1 ASC NULLS FIRST LIMIT ALL OFFSET 2; + QUERY PLAN +--------------------------------------------------------------------------------------- + Limit + Output: (min(c1)), c1 + -> Sort + Output: (min(c1)), c1 + Sort Key: fdw137_t2.c1 NULLS FIRST + -> Foreign Scan + Output: (min(c1)), c1 + Foreign Namespace: Aggregate on (mongo_fdw_regress.test_tbl2 fdw137_t2) +(8 rows) + +SELECT min(c1), c1 FROM fdw137_t2 GROUP BY c1 ORDER BY c1 ASC NULLS FIRST LIMIT ALL OFFSET 2; + min | c1 +-----+---- + 20 | 20 + 30 | 30 + 40 | 40 + 50 | 50 +(4 rows) + +-- Limit with -ve value. Shouldn't pushdown. +EXPLAIN (VERBOSE, COSTS FALSE) +SELECT c1, max(c1) FROM fdw137_t2 GROUP BY c1 ORDER BY 1 ASC NULLS FIRST LIMIT -1; + QUERY PLAN +-------------------------------------------------------------- + Limit + Output: c1, (max(c1)) + -> GroupAggregate + Output: c1, max(c1) + Group Key: fdw137_t2.c1 + -> Foreign Scan on public.fdw137_t2 + Output: _id, c1, c2, c3 + Foreign Namespace: mongo_fdw_regress.test_tbl2 +(8 rows) + +-- Should throw an error. +SELECT c1, max(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, max(c1) FROM fdw137_t2 GROUP BY c1 ORDER BY 1 ASC NULLS FIRST OFFSET -2; + QUERY PLAN +--------------------------------------------------------------------------------------- + Limit + Output: c1, (max(c1)) + -> Sort + Output: c1, (max(c1)) + Sort Key: fdw137_t2.c1 NULLS FIRST + -> Foreign Scan + Output: c1, (max(c1)) + Foreign Namespace: Aggregate on (mongo_fdw_regress.test_tbl2 fdw137_t2) +(8 rows) + +-- Should throw an error. +SELECT c1, max(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)) + -> GroupAggregate + Output: c1, avg(c1) + Group Key: fdw137_t2.c1 + -> Foreign Scan on public.fdw137_t2 + Output: _id, c1, c2, c3 + Foreign Namespace: mongo_fdw_regress.test_tbl2 +(8 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 (returns $0) + -> Foreign Scan + Output: (count(*)) + Foreign Namespace: Aggregate on (mongo_fdw_regress.test_tbl2 fdw137_t2) + -> Sort + Output: fdw137_t2.c1, (avg(fdw137_t2.c1)) + Sort Key: fdw137_t2.c1 NULLS FIRST + -> Foreign Scan + Output: fdw137_t2.c1, (avg(fdw137_t2.c1)) + Foreign Namespace: Aggregate on (mongo_fdw_regress.test_tbl2 fdw137_t2) +(12 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 -- Cleanup DELETE FROM fdw137_t1 WHERE c8 IS NULL; DELETE FROM fdw137_t1 WHERE c8 = 60; diff --git a/expected/aggregate_pushdown_3.out b/expected/aggregate_pushdown_3.out index 9d511ca..712db82 100644 --- a/expected/aggregate_pushdown_3.out +++ b/expected/aggregate_pushdown_3.out @@ -1464,6 +1464,181 @@ SELECT a32, sum(a32) FROM f_test_large GROUP BY 132 | 132 (3 rows) +-- FDW-131: Limit and offset pushdown with Aggregate pushdown. +SELECT min(c1), c1 FROM fdw137_t2 GROUP BY c1 ORDER BY c1; + min | c1 +-----+---- + 10 | 10 + 20 | 20 + 30 | 30 + 40 | 40 + 50 | 50 + | +(6 rows) + +EXPLAIN (VERBOSE, COSTS OFF) +SELECT min(c1), c1 FROM fdw137_t2 GROUP BY c1 ORDER BY c1 ASC NULLS FIRST LIMIT 1 OFFSET 1; + QUERY PLAN +-------------------------------------------------------------- + Limit + Output: (min(c1)), c1 + -> GroupAggregate + Output: min(c1), c1 + Group Key: fdw137_t2.c1 + -> Foreign Scan on public.fdw137_t2 + Output: _id, c1, c2, c3 + Foreign Namespace: mongo_fdw_regress.test_tbl2 +(8 rows) + +SELECT min(c1), c1 FROM fdw137_t2 GROUP BY c1 ORDER BY c1 ASC NULLS FIRST LIMIT 1 OFFSET 1; + min | c1 +-----+---- + 10 | 10 +(1 row) + +-- Limit 0, Offset 0 with aggregates. +EXPLAIN (VERBOSE, COSTS OFF) +SELECT min(c1), c1 FROM fdw137_t2 GROUP BY c1 ORDER BY c1 ASC NULLS FIRST LIMIT 0 OFFSET 0; + QUERY PLAN +-------------------------------------------------------------- + Limit + Output: (min(c1)), c1 + -> GroupAggregate + Output: min(c1), c1 + Group Key: fdw137_t2.c1 + -> Foreign Scan on public.fdw137_t2 + Output: _id, c1, c2, c3 + Foreign Namespace: mongo_fdw_regress.test_tbl2 +(8 rows) + +SELECT min(c1), c1 FROM fdw137_t2 GROUP BY c1 ORDER BY c1 ASC NULLS FIRST LIMIT 0 OFFSET 0; + min | c1 +-----+---- +(0 rows) + +-- Limit NULL +EXPLAIN (VERBOSE, COSTS OFF) +SELECT min(c1), c1 FROM fdw137_t2 GROUP BY c1 ORDER BY c1 ASC NULLS FIRST LIMIT NULL OFFSET 2; + QUERY PLAN +--------------------------------------------------------------------------------------- + Limit + Output: (min(c1)), c1 + -> Sort + Output: (min(c1)), c1 + Sort Key: fdw137_t2.c1 NULLS FIRST + -> Foreign Scan + Output: (min(c1)), c1 + Foreign Namespace: Aggregate on (mongo_fdw_regress.test_tbl2 fdw137_t2) +(8 rows) + +SELECT min(c1), c1 FROM fdw137_t2 GROUP BY c1 ORDER BY c1 ASC NULLS FIRST LIMIT NULL OFFSET 2; + min | c1 +-----+---- + 20 | 20 + 30 | 30 + 40 | 40 + 50 | 50 +(4 rows) + +-- Limit ALL +EXPLAIN (VERBOSE, COSTS OFF) +SELECT min(c1), c1 FROM fdw137_t2 GROUP BY c1 ORDER BY c1 ASC NULLS FIRST LIMIT ALL OFFSET 2; + QUERY PLAN +--------------------------------------------------------------------------------------- + Limit + Output: (min(c1)), c1 + -> Sort + Output: (min(c1)), c1 + Sort Key: fdw137_t2.c1 NULLS FIRST + -> Foreign Scan + Output: (min(c1)), c1 + Foreign Namespace: Aggregate on (mongo_fdw_regress.test_tbl2 fdw137_t2) +(8 rows) + +SELECT min(c1), c1 FROM fdw137_t2 GROUP BY c1 ORDER BY c1 ASC NULLS FIRST LIMIT ALL OFFSET 2; + min | c1 +-----+---- + 20 | 20 + 30 | 30 + 40 | 40 + 50 | 50 +(4 rows) + +-- Limit with -ve value. Shouldn't pushdown. +EXPLAIN (VERBOSE, COSTS FALSE) +SELECT c1, max(c1) FROM fdw137_t2 GROUP BY c1 ORDER BY 1 ASC NULLS FIRST LIMIT -1; + QUERY PLAN +-------------------------------------------------------------- + Limit + Output: c1, (max(c1)) + -> GroupAggregate + Output: c1, max(c1) + Group Key: fdw137_t2.c1 + -> Foreign Scan on public.fdw137_t2 + Output: _id, c1, c2, c3 + Foreign Namespace: mongo_fdw_regress.test_tbl2 +(8 rows) + +-- Should throw an error. +SELECT c1, max(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, max(c1) FROM fdw137_t2 GROUP BY c1 ORDER BY 1 ASC NULLS FIRST OFFSET -2; + QUERY PLAN +--------------------------------------------------------------------------------------- + Limit + Output: c1, (max(c1)) + -> Sort + Output: c1, (max(c1)) + Sort Key: fdw137_t2.c1 NULLS FIRST + -> Foreign Scan + Output: c1, (max(c1)) + Foreign Namespace: Aggregate on (mongo_fdw_regress.test_tbl2 fdw137_t2) +(8 rows) + +-- Should throw an error. +SELECT c1, max(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)) + -> GroupAggregate + Output: c1, avg(c1) + Group Key: fdw137_t2.c1 + -> Foreign Scan on public.fdw137_t2 + Output: _id, c1, c2, c3 + Foreign Namespace: mongo_fdw_regress.test_tbl2 +(8 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 (returns $0) + -> Foreign Scan + Output: (count(*)) + Foreign Namespace: Aggregate on (mongo_fdw_regress.test_tbl2 fdw137_t2) + -> Sort + Output: fdw137_t2.c1, (avg(fdw137_t2.c1)) + Sort Key: fdw137_t2.c1 NULLS FIRST + -> Foreign Scan + Output: fdw137_t2.c1, (avg(fdw137_t2.c1)) + Foreign Namespace: Aggregate on (mongo_fdw_regress.test_tbl2 fdw137_t2) +(12 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 -- Cleanup DELETE FROM fdw137_t1 WHERE c8 IS NULL; DELETE FROM fdw137_t1 WHERE c8 = 60; diff --git a/expected/join_pushdown.out b/expected/join_pushdown.out index 2ade800..7567ef4 100644 --- a/expected/join_pushdown.out +++ b/expected/join_pushdown.out @@ -100,12 +100,11 @@ SELECT d.c1, d.c2, e.c1, e.c2, e.c6, e.c8 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 ------------------------------------------------------------------------------------------------------- - Limit - -> Foreign Scan - Foreign Namespace: (mongo_fdw_regress.test_tbl2 d) LEFT JOIN (mongo_fdw_regress.test_tbl1 e) -(3 rows) + 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; @@ -672,17 +671,16 @@ 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 ----------------------------------------------------------------------------------------------------------------- + QUERY PLAN +---------------------------------------------------------------------------------------------------------- Sort Sort Key: l.c8 InitPlan 1 (returns $0) - -> Limit - -> Foreign Scan - Foreign Namespace: (mongo_fdw_regress.test_tbl1 f1) LEFT JOIN (mongo_fdw_regress.test_tbl2 f2) + -> 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 = $0) -(8 rows) +(7 rows) SELECT l.c1, l.c6, l.c8 FROM l_test_tbl1 l @@ -696,17 +694,16 @@ 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 ------------------------------------------------------------------------------------------------------------------ + QUERY PLAN +----------------------------------------------------------------------------------------------------------- Sort Sort Key: l.c8 InitPlan 1 (returns $0) - -> Limit - -> Foreign Scan - Foreign Namespace: (mongo_fdw_regress.test_tbl1 f1) INNER JOIN (mongo_fdw_regress.test_tbl2 f2) + -> 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 = $0) -(8 rows) +(7 rows) SELECT l.c1, l.c6, l.c8 FROM l_test_tbl1 l @@ -1352,6 +1349,177 @@ SELECT e.c1, d.c2 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 (returns $0) + -> 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 diff --git a/expected/join_pushdown_1.out b/expected/join_pushdown_1.out index e314dcb..87a9e0e 100644 --- a/expected/join_pushdown_1.out +++ b/expected/join_pushdown_1.out @@ -100,12 +100,11 @@ SELECT d.c1, d.c2, e.c1, e.c2, e.c6, e.c8 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 ------------------------------------------------------------------------------------------------------- - Limit - -> Foreign Scan - Foreign Namespace: (mongo_fdw_regress.test_tbl2 d) LEFT JOIN (mongo_fdw_regress.test_tbl1 e) -(3 rows) + 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; @@ -672,17 +671,16 @@ 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 ----------------------------------------------------------------------------------------------------------------- + QUERY PLAN +---------------------------------------------------------------------------------------------------------- Sort Sort Key: l.c8 InitPlan 1 (returns $0) - -> Limit - -> Foreign Scan - Foreign Namespace: (mongo_fdw_regress.test_tbl1 f1) LEFT JOIN (mongo_fdw_regress.test_tbl2 f2) + -> 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 = $0) -(8 rows) +(7 rows) SELECT l.c1, l.c6, l.c8 FROM l_test_tbl1 l @@ -696,17 +694,16 @@ 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 ------------------------------------------------------------------------------------------------------------------ + QUERY PLAN +----------------------------------------------------------------------------------------------------------- Sort Sort Key: l.c8 InitPlan 1 (returns $0) - -> Limit - -> Foreign Scan - Foreign Namespace: (mongo_fdw_regress.test_tbl1 f1) INNER JOIN (mongo_fdw_regress.test_tbl2 f2) + -> 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 = $0) -(8 rows) +(7 rows) SELECT l.c1, l.c6, l.c8 FROM l_test_tbl1 l @@ -1352,6 +1349,177 @@ SELECT e.c1, d.c2 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 (returns $0) + -> 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 diff --git a/expected/join_pushdown_2.out b/expected/join_pushdown_2.out index a362230..9605e7d 100644 --- a/expected/join_pushdown_2.out +++ b/expected/join_pushdown_2.out @@ -1355,6 +1355,185 @@ SELECT e.c1, d.c2 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 +--------------------------------------------------------------------------------------------------------- + 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) + +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 | 30 + 100 | 40 +(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 +--------------------------------------------------------------------------------------------------------- + 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) + +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 +--------------------------------------------------------------------------------------------------------- + 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) + +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 +--------------------------------------------------------------------------------------------------------- + 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) + +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 (returns $0) + -> 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 diff --git a/expected/join_pushdown_3.out b/expected/join_pushdown_3.out index af797df..0c3c59c 100644 --- a/expected/join_pushdown_3.out +++ b/expected/join_pushdown_3.out @@ -1355,6 +1355,185 @@ SELECT e.c1, d.c2 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 +--------------------------------------------------------------------------------------------------------- + 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) + +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 | 30 + 100 | 40 +(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 +--------------------------------------------------------------------------------------------------------- + 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) + +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 +--------------------------------------------------------------------------------------------------------- + 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) + +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 +--------------------------------------------------------------------------------------------------------- + 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) + +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 (returns $0) + -> 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; ERROR: unrecognized configuration parameter "enable_partitionwise_join" diff --git a/expected/limit_offset_pushdown.out b/expected/limit_offset_pushdown.out new file mode 100644 index 0000000..b797352 --- /dev/null +++ b/expected/limit_offset_pushdown.out @@ -0,0 +1,379 @@ +\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 'edb' user with 'edb' 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 (returns $0) + -> 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 (returns $0) + -> 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 (returns $0) + -> 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/expected/limit_offset_pushdown_1.out b/expected/limit_offset_pushdown_1.out new file mode 100644 index 0000000..b4d361b --- /dev/null +++ b/expected/limit_offset_pushdown_1.out @@ -0,0 +1,397 @@ +\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 'edb' user with 'edb' 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 +-------------------------------------------------------- + Limit + Output: c1, c2, c3 + -> Foreign Scan on public.fdw131_t1 + Output: c1, c2, c3 + Foreign Namespace: mongo_fdw_regress.test_tbl2 +(5 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 +-------------------------------------------------------- + Limit + Output: c1, c2, c3 + -> Foreign Scan on public.fdw131_t1 + Output: c1, c2, c3 + Foreign Namespace: mongo_fdw_regress.test_tbl2 +(5 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 +-------------------------------------------------------- + Limit + Output: c1, c2, c3 + -> Foreign Scan on public.fdw131_t1 + Output: c1, c2, c3 + Foreign Namespace: mongo_fdw_regress.test_tbl2 +(5 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 +-------------------------------------------------------- + Limit + Output: c1, c2, c3 + -> Foreign Scan on public.fdw131_t1 + Output: c1, c2, c3 + Foreign Namespace: mongo_fdw_regress.test_tbl2 +(5 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 +-------------------------------------------------------- + Limit + Output: c1, c2, c3 + -> Foreign Scan on public.fdw131_t1 + Output: c1, c2, c3 + Foreign Namespace: mongo_fdw_regress.test_tbl2 +(5 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 +-------------------------------------------------------- + Limit + Output: c1, c2, c3 + -> Foreign Scan on public.fdw131_t1 + Output: c1, c2, c3 + Foreign Namespace: mongo_fdw_regress.test_tbl2 +(5 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 +-------------------------------------------------------- + Limit + Output: c1, c2, c3 + -> Foreign Scan on public.fdw131_t1 + Output: c1, c2, c3 + Foreign Namespace: mongo_fdw_regress.test_tbl2 +(5 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 +-------------------------------------------------------- + Limit + Output: c1, c2, c3 + -> Foreign Scan on public.fdw131_t1 + Output: c1, c2, c3 + Foreign Namespace: mongo_fdw_regress.test_tbl2 +(5 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 +-------------------------------------------------------- + Limit + Output: c1, c2, c3 + -> Foreign Scan on public.fdw131_t1 + Output: c1, c2, c3 + Foreign Namespace: mongo_fdw_regress.test_tbl2 +(5 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 (returns $0) + -> 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 (returns $0) + -> 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 (returns $0) + -> 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/sql/aggregate_pushdown.sql b/sql/aggregate_pushdown.sql index 132cbd2..2fc622c 100644 --- a/sql/aggregate_pushdown.sql +++ b/sql/aggregate_pushdown.sql @@ -378,6 +378,50 @@ SELECT a32, sum(a32) FROM f_test_large GROUP BY 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; +-- FDW-131: Limit and offset pushdown with Aggregate pushdown. +SELECT min(c1), c1 FROM fdw137_t2 GROUP BY c1 ORDER BY c1; +EXPLAIN (VERBOSE, COSTS OFF) +SELECT min(c1), c1 FROM fdw137_t2 GROUP BY c1 ORDER BY c1 ASC NULLS FIRST LIMIT 1 OFFSET 1; +SELECT min(c1), c1 FROM fdw137_t2 GROUP BY c1 ORDER BY c1 ASC NULLS FIRST LIMIT 1 OFFSET 1; + +-- Limit 0, Offset 0 with aggregates. +EXPLAIN (VERBOSE, COSTS OFF) +SELECT min(c1), c1 FROM fdw137_t2 GROUP BY c1 ORDER BY c1 ASC NULLS FIRST LIMIT 0 OFFSET 0; +SELECT min(c1), c1 FROM fdw137_t2 GROUP BY c1 ORDER BY c1 ASC NULLS FIRST LIMIT 0 OFFSET 0; + +-- Limit NULL +EXPLAIN (VERBOSE, COSTS OFF) +SELECT min(c1), c1 FROM fdw137_t2 GROUP BY c1 ORDER BY c1 ASC NULLS FIRST LIMIT NULL OFFSET 2; +SELECT min(c1), c1 FROM fdw137_t2 GROUP BY c1 ORDER BY c1 ASC NULLS FIRST LIMIT NULL OFFSET 2; + +-- Limit ALL +EXPLAIN (VERBOSE, COSTS OFF) +SELECT min(c1), c1 FROM fdw137_t2 GROUP BY c1 ORDER BY c1 ASC NULLS FIRST LIMIT ALL OFFSET 2; +SELECT min(c1), c1 FROM fdw137_t2 GROUP BY c1 ORDER BY c1 ASC NULLS FIRST LIMIT ALL OFFSET 2; + +-- Limit with -ve value. Shouldn't pushdown. +EXPLAIN (VERBOSE, COSTS FALSE) +SELECT c1, max(c1) FROM fdw137_t2 GROUP BY c1 ORDER BY 1 ASC NULLS FIRST LIMIT -1; +-- Should throw an error. +SELECT c1, max(c1) FROM fdw137_t2 GROUP BY c1 ORDER BY 1 ASC NULLS FIRST LIMIT -1; + +-- Offset with -ve value. Shouldn't pushdown. +EXPLAIN (VERBOSE, COSTS FALSE) +SELECT c1, max(c1) FROM fdw137_t2 GROUP BY c1 ORDER BY 1 ASC NULLS FIRST OFFSET -2; +-- Should throw an error. +SELECT c1, max(c1) FROM fdw137_t2 GROUP BY c1 ORDER BY 1 ASC NULLS FIRST OFFSET -2; + +-- 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; +-- Should throw an error. +SELECT c1, avg(c1) FROM fdw137_t2 GROUP BY c1 ORDER BY c1 ASC NULLS FIRST LIMIT -1 OFFSET -2; + +-- 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)); +SELECT c1, avg(c1) FROM fdw137_t2 GROUP BY c1 ORDER BY c1 ASC NULLS FIRST LIMIT (1 - (SELECT COUNT(*) FROM fdw137_t2)); + -- Cleanup DELETE FROM fdw137_t1 WHERE c8 IS NULL; DELETE FROM fdw137_t1 WHERE c8 = 60; diff --git a/sql/join_pushdown.sql b/sql/join_pushdown.sql index 6c4db0a..05cb494 100644 --- a/sql/join_pushdown.sql +++ b/sql/join_pushdown.sql @@ -339,6 +339,66 @@ SELECT e.c1, d.c2 SELECT e.c1, d.c2 FROM f_test_tbl1 d CROSS JOIN f_test_tbl2 e ORDER BY e.c1, d.c2 LIMIT 10; +-- 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; +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; + +-- 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; +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; + +-- 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; +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; + +-- 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; +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; + +-- 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; +-- 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; + +-- 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; +-- 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; + +-- 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; +-- 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; + +-- 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)); +-- 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)); + -- Test partition-wise join SET enable_partitionwise_join TO on; diff --git a/sql/limit_offset_pushdown.sql b/sql/limit_offset_pushdown.sql new file mode 100644 index 0000000..9071483 --- /dev/null +++ b/sql/limit_offset_pushdown.sql @@ -0,0 +1,121 @@ +\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 'edb' user with 'edb' 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; + +-- 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; +SELECT c1, c2, c3 FROM fdw131_t1 ORDER BY 1 ASC NULLS FIRST LIMIT 2 OFFSET 2; + +-- 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; +SELECT c1, c2, c3 FROM fdw131_t1 ORDER BY 1 LIMIT 2 OFFSET 2; + +-- 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; +SELECT c1, c2, c3 FROM fdw131_t1 ORDER BY 1 ASC NULLS FIRST LIMIT 2 OFFSET 2; +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; +SELECT c1, c2, c3 FROM fdw131_t1 ORDER BY 2 DESC NULLS LAST LIMIT 3; + +-- 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; +SELECT c1, c2, c3 FROM fdw131_t1 ORDER BY 3 DESC NULLS LAST LIMIT round(3.2) OFFSET 2; + +-- 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; +SELECT c1, c2, c3 FROM fdw131_t1 ORDER BY 3 ASC NULLS FIRST OFFSET 2; + +-- Limit ALL +EXPLAIN (VERBOSE, COSTS FALSE) +SELECT c1, c2, c3 FROM fdw131_t1 ORDER BY 1 ASC NULLS FIRST LIMIT ALL; +SELECT c1, c2, c3 FROM fdw131_t1 ORDER BY 1 ASC NULLS FIRST LIMIT ALL; + +-- 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; +SELECT c1, c2, c3 FROM fdw131_t1 ORDER BY 1 ASC NULLS FIRST LIMIT ALL OFFSET 1; + +-- Limit NULL +EXPLAIN (VERBOSE, COSTS FALSE) +SELECT c1, c2, c3 FROM fdw131_t1 ORDER BY 3 ASC NULLS FIRST LIMIT NULL; +SELECT c1, c2, c3 FROM fdw131_t1 ORDER BY 3 ASC NULLS FIRST LIMIT NULL; +EXPLAIN (VERBOSE, COSTS FALSE) +SELECT c1, c2, c3 FROM fdw131_t1 ORDER BY 3 ASC NULLS FIRST LIMIT NULL OFFSET 2; +SELECT c1, c2, c3 FROM fdw131_t1 ORDER BY 3 ASC NULLS FIRST LIMIT NULL OFFSET 2; + +-- Limit 0 and Offset 0 +EXPLAIN (VERBOSE, COSTS FALSE) +SELECT c1, c2, c3 FROM fdw131_t1 ORDER BY 1 ASC NULLS FIRST LIMIT 0; +SELECT c1, c2, c3 FROM fdw131_t1 ORDER BY 1 ASC NULLS FIRST LIMIT 0; +EXPLAIN (VERBOSE, COSTS FALSE) +SELECT c1, c2, c3 FROM fdw131_t1 ORDER BY 1 ASC NULLS FIRST LIMIT 0 OFFSET 0; +SELECT c1, c2, c3 FROM fdw131_t1 ORDER BY 1 ASC NULLS FIRST LIMIT 0 OFFSET 0; + +-- Offset NULL. +EXPLAIN (VERBOSE, COSTS FALSE) +SELECT c1, c2, c3 FROM fdw131_t1 ORDER BY 2 ASC NULLS FIRST LIMIT 5 OFFSET NULL; +SELECT c1, c2, c3 FROM fdw131_t1 ORDER BY 2 ASC NULLS FIRST LIMIT 5 OFFSET NULL; + +-- 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); +SELECT c1, c2, c3 FROM fdw131_t1 ORDER BY 2 LIMIT (SELECT COUNT(*) FROM fdw131_t1); + +-- 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)); +SELECT c1, c2, c3 FROM fdw131_t1 ORDER BY 1 ASC NULLS FIRST LIMIT (10 - (SELECT COUNT(*) FROM fdw131_t1)); + +-- 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; +-- Should throw an error. +SELECT c1, c2, c3 FROM fdw131_t1 ORDER BY 1 ASC NULLS FIRST LIMIT -1; + +-- 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; +-- Should throw an error. +SELECT c1, c2, c3 FROM fdw131_t1 ORDER BY 1 ASC NULLS FIRST OFFSET -2; + +-- 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; +-- Should throw an error. +SELECT c1, c2, c3 FROM fdw131_t1 ORDER BY 1 ASC NULLS FIRST LIMIT -1 OFFSET -2; + +-- 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)); +SELECT c1, c2, c3 FROM fdw131_t1 ORDER BY 1 ASC NULLS FIRST LIMIT (1 - (SELECT COUNT(*) FROM fdw131_t1)); + +DROP FOREIGN TABLE fdw131_t1; +DROP USER MAPPING FOR public SERVER mongo_server; +DROP SERVER mongo_server; +DROP EXTENSION mongo_fdw;