PG18 - Handle PG18’s synthetic `RTE_GROUP` in `FindReferencedTableColumn` for correct GROUP BY pushdown (#8034)

Fixes #8032 

PostgreSQL 18 introduces a dedicated “grouping-step” range table entry
(`RTE_GROUP`) whose target columns are exactly the expressions in our
`GROUP BY` clause, rather than hiding them as `resjunk` items. In
Citus’s distributed planner, the function `FindReferencedTableColumn`
must be able to map from a `Var` referencing a grouped column back to
the underlying table column. Without special handling for `RTE_GROUP`,
queries that rely on pushdown of `GROUP BY` expressions can fail or
mis-identify their target columns.

This PR adds support for `RTE_GROUP` in Citus when built against PG 18
or later, ensuring that:

* Each grouped expression is correctly resolved.
* The pushdown planner can trace a `Var`’s `varattno` into the
corresponding `groupexprs` list.
* Existing behavior on PG < 18 is unchanged.

---

## What’s Changed

In **`src/backend/distributed/planner/multi_logical_optimizer.c`**,
inside `FindReferencedTableColumn`:

* **Under** `#if PG_VERSION_NUM >= PG_VERSION_18`
  Introduce an `else if` branch for

  ```c
  rangeTableEntry->rtekind == RTE_GROUP
  ```

* **Extraction of grouped expressions:**

  ```c
  List *groupexprs   = rangeTableEntry->groupexprs;
  AttrNumber groupIndex = candidateColumn->varattno - 1;
  ```

* **Safety check** to guard against malformed `Var` numbers:

  ```c
  if (groupIndex < 0 || groupIndex >= list_length(groupexprs))
      return;    /* malformed Var */
  ```

* **Recursive descent:**
  Fetch the corresponding expression from `groupexprs` and call

  ```c
  FindReferencedTableColumn(groupExpr, parentQueryList, query,
                            column, rteContainingReferencedColumn,
                            skipOuterVars);
  ```

so that the normal resolution logic applies to the underlying
expression.

* **Unchanged code path** for PG < 18 and for other `rtekind` values.

---
pull/8023/head^2
Mehmet YILMAZ 2025-07-16 23:23:14 +03:00 committed by GitHub
parent 9e42f3f2c4
commit 5005be31e6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 23 additions and 0 deletions

View File

@ -4557,6 +4557,29 @@ FindReferencedTableColumn(Expr *columnExpression, List *parentQueryList, Query *
FindReferencedTableColumn(joinColumn, parentQueryList, query, column, FindReferencedTableColumn(joinColumn, parentQueryList, query, column,
rteContainingReferencedColumn, skipOuterVars); rteContainingReferencedColumn, skipOuterVars);
} }
#if PG_VERSION_NUM >= PG_VERSION_18
else if (rangeTableEntry->rtekind == RTE_GROUP)
{
/*
* PG 18: synthetic GROUP RTE. Each groupexprs item corresponds to the
* columns produced by the grouping step, in the *same ordinal order* as
* the Vars that reference them.
*/
List *groupexprs = rangeTableEntry->groupexprs;
AttrNumber groupIndex = candidateColumn->varattno - 1;
/* this must always hold unless upstream Postgres mis-constructed the RTE_GROUP */
Assert(groupIndex >= 0 && groupIndex < list_length(groupexprs));
Expr *groupExpr = (Expr *) list_nth(groupexprs, groupIndex);
/* Recurse on the underlying expression (stay in the same query) */
FindReferencedTableColumn(groupExpr, parentQueryList, query,
column, rteContainingReferencedColumn,
skipOuterVars);
}
#endif /* PG_VERSION_NUM >= 180000 */
else if (rangeTableEntry->rtekind == RTE_CTE) else if (rangeTableEntry->rtekind == RTE_CTE)
{ {
/* /*