I'm working on a patch [1] to get the planner to consider adding PathKeys to satisfy ORDER BY / DISTINCT aggregates. I think this has led me to discover some problems with postgres_fdw's handling of pushing down ORDER BY clauses into the foreign server.
The following test exists in the postgres_fdw module: create operator class my_op_class for type int using btree family my_op_family as operator 1 public.<^, operator 3 public.=^, operator 5 public.>^, function 1 my_op_cmp(int, int); -- This will not be pushed as user defined sort operator is not part of the -- extension yet. explain (verbose, costs off) select array_agg(c1 order by c1 using operator(public.<^)) from ft2 where c2 = 6 and c1 < 100 group by c2; QUERY PLAN -------------------------------------------------------------------------------------------- GroupAggregate Output: array_agg(c1 ORDER BY c1 USING <^ NULLS LAST), c2 Group Key: ft2.c2 -> Foreign Scan on public.ft2 Output: c1, c2 Remote SQL: SELECT "C 1", c2 FROM "S 1"."T 1" WHERE (("C 1" < 100)) AND ((c2 = 6)) (6 rows) Here the test claims that it wants to ensure that the order by using operator(public.<^) is not pushed down into the foreign scan. However, unless I'm mistaken, it seems there's a completely wrong assumption there that the planner would even attempt that. In current master we don't add PathKeys for ORDER BY aggregates, why would that sort get pushed down in the first place? If I adjust that query to something that would have the planner set pathkeys for, it does push the ORDER BY to the foreign server without any consideration that the sort operator is not shippable to the foreign server. postgres=# explain verbose select * from ft2 order by c1 using operator(public.<^); QUERY PLAN ------------------------------------------------------------------------------------------------------- Foreign Scan on public.ft2 (cost=100.28..169.27 rows=1000 width=88) Output: c1, c2, c3, c4, c5, c6, c7, c8 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" ORDER BY "C 1" ASC NULLS LAST (3 rows) Am I missing something here, or is postgres_fdw.c's get_useful_pathkeys_for_relation() just broken? David [1] https://www.postgresql.org/message-id/flat/1882015.KPgzjnsp5C%40aivenronan#159e89188e172ca38cb28ef7c5be9b2c