Re: Inconsistent Behavior of GROUP BY ROLLUP in v17 vs master
От | Richard Guo |
---|---|
Тема | Re: Inconsistent Behavior of GROUP BY ROLLUP in v17 vs master |
Дата | |
Msg-id | CAMbWs49CGO8MPJrn6xcduv39GmgmKPnRKGSCA0B5DLsKee_bVQ@mail.gmail.com обсуждение исходный текст |
Ответ на | Re: Inconsistent Behavior of GROUP BY ROLLUP in v17 vs master (Tom Lane <tgl@sss.pgh.pa.us>) |
Ответы |
Re: Inconsistent Behavior of GROUP BY ROLLUP in v17 vs master
|
Список | pgsql-hackers |
On Wed, Sep 24, 2025 at 10:23 AM Tom Lane <tgl@sss.pgh.pa.us> wrote: > Yeah, I don't think the havingClause being constant-false is the > key point here. I've not looked closely at 67a54b9e, but I suspect > that anything Var-free is potentially an issue. Or it might even > fail for something that has Vars but is non-strict. > > The core of the problem though is that the aggregation node will > issue an all-nulls row that did not come from its input, and we > have to be sure that the HAVING clause is properly evaluated > for that row. I think the issue is that an empty grouping set can produce a row out of nowhere, and pushing down HAVING clauses in this case may cause us to fail to filter out that row. Currently, non-variable-free HAVING clauses aren't pushed down when there is an empty grouping set, because the empty grouping set would nullify the vars referenced in those clauses, and we have logic in place to prevent their pushdown. However, we (I) overlooked variable-free HAVING clauses. If there are only empty grouping sets, this is not a problem since a copy of the HAVING clauses is retained in HAVING. The issue arises when there are both nonempty and empty grouping sets. In summary, the problem occurs when both of the following conditions are met: 1) there are both nonempty and empty grouping sets, 2) there are variable-free HAVING clauses. I think the following change fixes this problem. foreach(l, (List *) parse->havingQual) { Node *havingclause = (Node *) lfirst(l); + Relids having_relids; if (contain_agg_clause(havingclause) || contain_volatile_functions(havingclause) || contain_subplans(havingclause) || (parse->groupClause && parse->groupingSets && - bms_is_member(root->group_rtindex, pull_varnos(root, havingclause)))) + ((having_relids = pull_varnos(root, havingclause)) == NULL || + bms_is_member(root->group_rtindex, having_relids)))) { /* keep it in HAVING */ newHaving = lappend(newHaving, havingclause); This change essentially prevents variable-free HAVING clauses from being pushed down when there are any nonempty grouping sets. Of course, this could be done more precisely -- for example, we could restrict the prevention only to cases where empty grouping sets are also present, but I'm not sure it's worth the effort. - Richard
В списке pgsql-hackers по дате отправления: