fix-agglevelsup-calculation-with-CTEs.patch
text/x-diff
Filename: fix-agglevelsup-calculation-with-CTEs.patch
Type: text/x-diff
Part: 0
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: unified
| File | + | − |
|---|---|---|
| src/backend/parser/parse_agg.c | 28 | 1 |
diff --git a/src/backend/parser/parse_agg.c b/src/backend/parser/parse_agg.c
index 0ac8966e30f..2bef05b4833 100644
--- a/src/backend/parser/parse_agg.c
+++ b/src/backend/parser/parse_agg.c
@@ -791,6 +791,33 @@ check_agg_arguments_walker(Node *node,
parser_errposition(context->pstate,
((WindowFunc *) node)->location)));
}
+
+ if (IsA(node, RangeTblEntry))
+ {
+ /*
+ * CTE references act as though they were Vars of the CTE's level.
+ * Typically this doesn't matter because the sub-select containing the
+ * CTE RTE will also contain Vars referencing that RTE; but if it does
+ * not, we end with an invalid query tree if we don't do this.
+ */
+ RangeTblEntry *rte = (RangeTblEntry *) node;
+
+ if (rte->rtekind == RTE_CTE)
+ {
+ int ctelevelsup = rte->ctelevelsup;
+
+ /* convert levelsup to frame of reference of original query */
+ ctelevelsup -= context->sublevels_up;
+ /* ignore local CTEs of subqueries */
+ if (ctelevelsup >= 0)
+ {
+ if (context->min_varlevel < 0 ||
+ context->min_varlevel > ctelevelsup)
+ context->min_varlevel = ctelevelsup;
+ }
+ }
+ return false; /* allow range_table_walker to continue */
+ }
if (IsA(node, Query))
{
/* Recurse into subselects */
@@ -800,7 +827,7 @@ check_agg_arguments_walker(Node *node,
result = query_tree_walker((Query *) node,
check_agg_arguments_walker,
context,
- 0);
+ QTW_EXAMINE_RTES_BEFORE);
context->sublevels_up--;
return result;
}