aboutsummaryrefslogtreecommitdiff
path: root/contrib/postgres_fdw/deparse.c
diff options
context:
space:
mode:
authorDavid Rowley <drowley@postgresql.org>2024-03-11 12:27:11 +1300
committerDavid Rowley <drowley@postgresql.org>2024-03-11 12:27:11 +1300
commitc399248b3b44bd6cece1ada47eee346b67a88a0a (patch)
tree75aea86580cabbdaa47c39b3155166161972701f /contrib/postgres_fdw/deparse.c
parent7b8e2ae2fd3bec55e2d8c51e49871954851b5df8 (diff)
downloadpostgresql-c399248b3b44bd6cece1ada47eee346b67a88a0a.tar.gz
postgresql-c399248b3b44bd6cece1ada47eee346b67a88a0a.zip
Fix deparsing of Consts in postgres_fdw ORDER BY
For UNION ALL queries where a union child query contained a foreign table, if the targetlist of that query contained a constant, and the top-level query performed an ORDER BY which contained the column for the constant value, then postgres_fdw would find the EquivalenceMember with the Const and then try to produce an ORDER BY containing that Const. This caused problems with INT typed Consts as these could appear to be requests to order by an ordinal column position rather than the constant value. This could lead to either an error such as: ERROR: ORDER BY position <int const> is not in select list or worse, if the constant value is a valid column, then we could just sort by the wrong column altogether. Here we fix this issue by just not including these Consts in the ORDER BY clause. In passing, add a new section for testing ORDER BY in the postgres_fdw tests and move two existing tests which were misplaced in the WHERE clause testing section into it. Reported-by: Michał Kłeczek Reviewed-by: Ashutosh Bapat, Richard Guo Bug: #18381 Discussion: https://postgr.es/m/0714C8B8-8D82-4ABB-9F8D-A0C3657E7B6E%40kleczek.org Discussion: https://postgr.es/m/18381-137456acd168bf93%40postgresql.org Backpatch-through: 12, oldest supported version
Diffstat (limited to 'contrib/postgres_fdw/deparse.c')
-rw-r--r--contrib/postgres_fdw/deparse.c25
1 files changed, 21 insertions, 4 deletions
diff --git a/contrib/postgres_fdw/deparse.c b/contrib/postgres_fdw/deparse.c
index 8fc66fa11c7..8787c00d3eb 100644
--- a/contrib/postgres_fdw/deparse.c
+++ b/contrib/postgres_fdw/deparse.c
@@ -3912,13 +3912,12 @@ appendOrderByClause(List *pathkeys, bool has_final_sort,
{
ListCell *lcell;
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);
@@ -3952,6 +3951,26 @@ appendOrderByClause(List *pathkeys, bool has_final_sort,
em_expr = em->em_expr;
/*
+ * If the member is 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, an integer literal would be
+ * seen as an ordinal column position rather than a value to sort by.
+ * deparseConst() does have code to handle this, but it seems less
+ * effort on all accounts just to skip these for ORDER BY clauses.
+ */
+ if (IsA(em_expr, Const))
+ continue;
+
+ if (!gotone)
+ {
+ appendStringInfoString(buf, " ORDER BY ");
+ gotone = true;
+ }
+ else
+ appendStringInfoString(buf, ", ");
+
+ /*
* Lookup the operator corresponding to the strategy in the opclass.
* The datatype used by the opfamily is not necessarily the same as
* the expression type (for array types for example).
@@ -3965,7 +3984,6 @@ appendOrderByClause(List *pathkeys, bool has_final_sort,
pathkey->pk_strategy, em->em_datatype, em->em_datatype,
pathkey->pk_opfamily);
- appendStringInfoString(buf, delim);
deparseExpr(em_expr, context);
/*
@@ -3975,7 +3993,6 @@ appendOrderByClause(List *pathkeys, bool has_final_sort,
appendOrderBySuffix(oprid, exprType((Node *) em_expr),
pathkey->pk_nulls_first, context);
- delim = ", ";
}
reset_transmission_modes(nestlevel);
}