Skip to content

Commit 6e4eeaf

Browse files
committed
fix > ANY
1 parent f4dfe97 commit 6e4eeaf

8 files changed

Lines changed: 137 additions & 14 deletions

src/deparse.c

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -427,12 +427,18 @@ foreign_expr_walker(Node * node,
427427
return false;
428428

429429
/*
430-
* ANY deparsing expects testexpr to be a simple OpExpr
431-
* (single-column correlation). Reject multi-column cases.
430+
* ANY deparsing expects testexpr to be a simple equality
431+
* OpExpr. Reject multi-column and non-equality cases.
432+
* Non-equality ANY (e.g. > ANY) normally goes through
433+
* the join path, but guard here too.
432434
*/
433-
if (subplan->subLinkType == ANY_SUBLINK &&
434-
(!subplan->testexpr || !IsA(subplan->testexpr, OpExpr)))
435-
return false;
435+
if (subplan->subLinkType == ANY_SUBLINK)
436+
{
437+
if (!subplan->testexpr || !IsA(subplan->testexpr, OpExpr))
438+
return false;
439+
if (!chfdw_is_equal_op(((OpExpr *) subplan->testexpr)->opno))
440+
return false;
441+
}
436442

437443
/* Walk testexpr for shippability (outer-query refs) */
438444
if (subplan->testexpr &&

src/fdw.c.in

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1853,16 +1853,27 @@ foreign_join_ok(PlannerInfo * root, RelOptInfo * joinrel, JoinType jointype,
18531853
}
18541854

18551855
/*
1856-
* ClickHouse requires SEMI JOINs to have an ON clause with join
1857-
* conditions. Reject uncorrelated EXISTS subqueries that have no join
1858-
* keys.
1859-
*
1860-
* XXX Change to use ClickHouse EXISTS in this case?
1861-
* https://clickhouse.com/docs/sql-reference/operators/exists
1856+
* ClickHouse SEMI/ANTI JOINs require at least one equi-join key in ON.
1857+
* Reject when joinclauses has no equality referencing both sides
1858+
* (e.g. uncorrelated EXISTS, or > ANY producing non-equi semi-join).
18621859
*/
1863-
if ((jointype == JOIN_SEMI || jointype == JOIN_ANTI) &&
1864-
fpinfo->joinclauses == NIL)
1865-
return false;
1860+
if (jointype == JOIN_SEMI || jointype == JOIN_ANTI)
1861+
{
1862+
bool has_equi_key = false;
1863+
1864+
foreach(lc, fpinfo->joinclauses)
1865+
{
1866+
RestrictInfo *rinfo = lfirst_node(RestrictInfo, lc);
1867+
1868+
if (is_simple_join_clause((Expr *) rinfo))
1869+
{
1870+
has_equi_key = true;
1871+
break;
1872+
}
1873+
}
1874+
if (!has_equi_key)
1875+
return false;
1876+
}
18661877

18671878
/* Mark that this join can be pushed down safely */
18681879
fpinfo->pushdown_safe = true;

test/expected/subquery_pushdown.out

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -636,6 +636,26 @@ ORDER BY id;
636636
Remote SQL: SELECT amount FROM subquery_test.spd_orders WHERE ((status = 'closed'))
637637
(10 rows)
638638

639+
-- > ANY(subquery) should NOT push down (non-equality ANY_SUBLINK)
640+
EXPLAIN (VERBOSE, COSTS OFF)
641+
SELECT id, amount FROM spd_orders
642+
WHERE amount > ANY (SELECT amount FROM spd_orders WHERE status = 'closed')
643+
ORDER BY id;
644+
QUERY PLAN
645+
-----------------------------------------------------------------------------------------------------------
646+
Nested Loop Semi Join
647+
Output: spd_orders.id, spd_orders.amount
648+
Join Filter: (spd_orders.amount > spd_orders_1.amount)
649+
-> Foreign Scan on subquery_test.spd_orders
650+
Output: spd_orders.id, spd_orders.cust_id, spd_orders.status, spd_orders.amount, spd_orders.odate
651+
Remote SQL: SELECT id, amount FROM subquery_test.spd_orders ORDER BY id ASC NULLS LAST
652+
-> Materialize
653+
Output: spd_orders_1.amount
654+
-> Foreign Scan on subquery_test.spd_orders spd_orders_1
655+
Output: spd_orders_1.amount
656+
Remote SQL: SELECT amount FROM subquery_test.spd_orders WHERE ((status = 'closed'))
657+
(11 rows)
658+
639659
-- Scalar subquery with ORDER BY ... LIMIT
640660
EXPLAIN (VERBOSE, COSTS OFF)
641661
SELECT id,

test/expected/subquery_pushdown_1.out

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -630,6 +630,26 @@ ORDER BY id;
630630
Remote SQL: SELECT amount FROM subquery_test.spd_orders WHERE ((status = 'closed'))
631631
(10 rows)
632632

633+
-- > ANY(subquery) should NOT push down (non-equality ANY_SUBLINK)
634+
EXPLAIN (VERBOSE, COSTS OFF)
635+
SELECT id, amount FROM spd_orders
636+
WHERE amount > ANY (SELECT amount FROM spd_orders WHERE status = 'closed')
637+
ORDER BY id;
638+
QUERY PLAN
639+
-----------------------------------------------------------------------------------------------------------
640+
Nested Loop Semi Join
641+
Output: spd_orders.id, spd_orders.amount
642+
Join Filter: (spd_orders.amount > spd_orders_1.amount)
643+
-> Foreign Scan on subquery_test.spd_orders
644+
Output: spd_orders.id, spd_orders.cust_id, spd_orders.status, spd_orders.amount, spd_orders.odate
645+
Remote SQL: SELECT id, amount FROM subquery_test.spd_orders ORDER BY id ASC NULLS LAST
646+
-> Materialize
647+
Output: spd_orders_1.amount
648+
-> Foreign Scan on subquery_test.spd_orders spd_orders_1
649+
Output: spd_orders_1.amount
650+
Remote SQL: SELECT amount FROM subquery_test.spd_orders WHERE ((status = 'closed'))
651+
(11 rows)
652+
633653
-- Scalar subquery with ORDER BY ... LIMIT
634654
EXPLAIN (VERBOSE, COSTS OFF)
635655
SELECT id,

test/expected/subquery_pushdown_2.out

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -636,6 +636,26 @@ ORDER BY id;
636636
Remote SQL: SELECT amount FROM subquery_test.spd_orders WHERE ((status = 'closed'))
637637
(10 rows)
638638

639+
-- > ANY(subquery) should NOT push down (non-equality ANY_SUBLINK)
640+
EXPLAIN (VERBOSE, COSTS OFF)
641+
SELECT id, amount FROM spd_orders
642+
WHERE amount > ANY (SELECT amount FROM spd_orders WHERE status = 'closed')
643+
ORDER BY id;
644+
QUERY PLAN
645+
-----------------------------------------------------------------------------------------------------------
646+
Nested Loop Semi Join
647+
Output: spd_orders.id, spd_orders.amount
648+
Join Filter: (spd_orders.amount > spd_orders_1.amount)
649+
-> Foreign Scan on subquery_test.spd_orders
650+
Output: spd_orders.id, spd_orders.cust_id, spd_orders.status, spd_orders.amount, spd_orders.odate
651+
Remote SQL: SELECT id, amount FROM subquery_test.spd_orders ORDER BY id ASC NULLS LAST
652+
-> Materialize
653+
Output: spd_orders_1.amount
654+
-> Foreign Scan on subquery_test.spd_orders spd_orders_1
655+
Output: spd_orders_1.amount
656+
Remote SQL: SELECT amount FROM subquery_test.spd_orders WHERE ((status = 'closed'))
657+
(11 rows)
658+
639659
-- Scalar subquery with ORDER BY ... LIMIT
640660
EXPLAIN (VERBOSE, COSTS OFF)
641661
SELECT id,

test/expected/subquery_pushdown_3.out

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -636,6 +636,26 @@ ORDER BY id;
636636
Remote SQL: SELECT amount FROM subquery_test.spd_orders WHERE ((status = 'closed'))
637637
(10 rows)
638638

639+
-- > ANY(subquery) should NOT push down (non-equality ANY_SUBLINK)
640+
EXPLAIN (VERBOSE, COSTS OFF)
641+
SELECT id, amount FROM spd_orders
642+
WHERE amount > ANY (SELECT amount FROM spd_orders WHERE status = 'closed')
643+
ORDER BY id;
644+
QUERY PLAN
645+
-----------------------------------------------------------------------------------------------------------
646+
Nested Loop Semi Join
647+
Output: spd_orders.id, spd_orders.amount
648+
Join Filter: (spd_orders.amount > spd_orders_1.amount)
649+
-> Foreign Scan on subquery_test.spd_orders
650+
Output: spd_orders.id, spd_orders.cust_id, spd_orders.status, spd_orders.amount, spd_orders.odate
651+
Remote SQL: SELECT id, amount FROM subquery_test.spd_orders ORDER BY id ASC NULLS LAST
652+
-> Materialize
653+
Output: spd_orders_1.amount
654+
-> Foreign Scan on subquery_test.spd_orders spd_orders_1
655+
Output: spd_orders_1.amount
656+
Remote SQL: SELECT amount FROM subquery_test.spd_orders WHERE ((status = 'closed'))
657+
(11 rows)
658+
639659
-- Scalar subquery with ORDER BY ... LIMIT
640660
EXPLAIN (VERBOSE, COSTS OFF)
641661
SELECT id,

test/expected/subquery_pushdown_4.out

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -656,6 +656,26 @@ ORDER BY id;
656656
Remote SQL: SELECT amount FROM subquery_test.spd_orders WHERE ((status = 'closed'))
657657
(10 rows)
658658

659+
-- > ANY(subquery) should NOT push down (non-equality ANY_SUBLINK)
660+
EXPLAIN (VERBOSE, COSTS OFF)
661+
SELECT id, amount FROM spd_orders
662+
WHERE amount > ANY (SELECT amount FROM spd_orders WHERE status = 'closed')
663+
ORDER BY id;
664+
QUERY PLAN
665+
-----------------------------------------------------------------------------------------------------------
666+
Nested Loop Semi Join
667+
Output: spd_orders.id, spd_orders.amount
668+
Join Filter: (spd_orders.amount > spd_orders_1.amount)
669+
-> Foreign Scan on subquery_test.spd_orders
670+
Output: spd_orders.id, spd_orders.cust_id, spd_orders.status, spd_orders.amount, spd_orders.odate
671+
Remote SQL: SELECT id, amount FROM subquery_test.spd_orders ORDER BY id ASC NULLS LAST
672+
-> Materialize
673+
Output: spd_orders_1.amount
674+
-> Foreign Scan on subquery_test.spd_orders spd_orders_1
675+
Output: spd_orders_1.amount
676+
Remote SQL: SELECT amount FROM subquery_test.spd_orders WHERE ((status = 'closed'))
677+
(11 rows)
678+
659679
-- Scalar subquery with ORDER BY ... LIMIT
660680
EXPLAIN (VERBOSE, COSTS OFF)
661681
SELECT id,

test/sql/subquery_pushdown.sql

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,12 @@ SELECT id, amount FROM spd_orders
336336
WHERE amount > ALL (SELECT amount FROM spd_orders WHERE status = 'closed')
337337
ORDER BY id;
338338

339+
-- > ANY(subquery) should NOT push down (non-equality ANY_SUBLINK)
340+
EXPLAIN (VERBOSE, COSTS OFF)
341+
SELECT id, amount FROM spd_orders
342+
WHERE amount > ANY (SELECT amount FROM spd_orders WHERE status = 'closed')
343+
ORDER BY id;
344+
339345
-- Scalar subquery with ORDER BY ... LIMIT
340346
EXPLAIN (VERBOSE, COSTS OFF)
341347
SELECT id,

0 commit comments

Comments
 (0)