On Thu, 7 Mar 2024 at 19:09, Michał Kłeczek <mic...@kleczek.org> wrote: > > The following query: > > SELECT * FROM ( > SELECT 2023 AS year, * FROM remote_table_1 > UNION ALL > SELECT 2022 AS year, * FROM remote_table_2 > ) > ORDER BY year DESC; > > yields the following remote query: > > SELECT [columns] FROM remote_table_1 ORDER BY 2023 DESC > > and subsequently fails remote execution. > > > Not really sure where the problem is - the planner or postgres_fdw. > I guess it is postgres_fdw not filtering out ordering keys.
Interesting. I've attached a self-contained recreator for the casual passerby. I think the fix should go in appendOrderByClause(). It's at that point we look for the EquivalenceMember for the relation and can easily discover if the em_expr is a Const. I think we can safely just skip doing any ORDER BY <const> stuff and not worry about if the literal format of the const will appear as a reference to an ordinal column position in the ORDER BY clause. Something like the attached patch I think should work. I wonder if we need a test... David
diff --git a/contrib/postgres_fdw/deparse.c b/contrib/postgres_fdw/deparse.c index 8fc66fa11c..2f4ed33173 100644 --- a/contrib/postgres_fdw/deparse.c +++ b/contrib/postgres_fdw/deparse.c @@ -3914,11 +3914,11 @@ appendOrderByClause(List *pathkeys, bool has_final_sort, int nestlevel; const char *delim = " "; StringInfo buf = context->buf; + bool gotone = false; /* Make sure any constants in the exprs are printed portably */ nestlevel = set_transmission_modes(); - appendStringInfoString(buf, " ORDER BY"); foreach(lcell, pathkeys) { PathKey *pathkey = lfirst(lcell); @@ -3949,6 +3949,21 @@ appendOrderByClause(List *pathkeys, bool has_final_sort, if (em == NULL) elog(ERROR, "could not find pathkey item to sort"); + /* + * If the member just has a Const expression then we needn't add it to + * the ORDER BY clause. This can happen in UNION ALL queries where the + * union child targetlist has a Const. Adding these would be wasteful, + * but also, for INT columns, putting an integer literal will be seen + * as an ordinal column position rather than a value to sort by, so we + * must skip these. + */ + if (IsA(em->em_expr, Const)) + continue; + + if (!gotone) + appendStringInfoString(buf, " ORDER BY"); + gotone = true; + em_expr = em->em_expr; /*
demo_of_postgres_fdw_order_by_const_bug.sql
Description: Binary data