mirror of
https://github.com/postgres/postgres.git
synced 2025-10-27 00:12:01 +03:00
Avoid listing ungrouped Vars in the targetlist of Agg-underneath-Window.
Regular aggregate functions in combination with, or within the arguments of, window functions are OK per spec; they have the semantics that the aggregate output rows are computed and then we run the window functions over that row set. (Thus, this combination is not really useful unless there's a GROUP BY so that more than one aggregate output row is possible.) The case without GROUP BY could fail, as recently reported by Jeff Davis, because sloppy construction of the Agg node's targetlist resulted in extra references to possibly-ungrouped Vars appearing outside the aggregate function calls themselves. See the added regression test case for an example. Fixing this requires modifying the API of flatten_tlist and its underlying function pull_var_clause. I chose to make pull_var_clause's API for aggregates identical to what it was already doing for placeholders, since the useful behaviors turn out to be the same (error, report node as-is, or recurse into it). I also tightened the error checking in this area a bit: if it was ever valid to see an uplevel Var, Aggref, or PlaceHolderVar here, that was a long time ago, so complain instead of ignoring them. Backpatch into 9.1. The failure exists in 8.4 and 9.0 as well, but seeing that it only occurs in a basically-useless corner case, it doesn't seem worth the risks of changing a function API in a minor release. There might be third-party code using pull_var_clause.
This commit is contained in:
@@ -48,7 +48,6 @@ extern Expr *make_ands_explicit(List *andclauses);
|
||||
extern List *make_ands_implicit(Expr *clause);
|
||||
|
||||
extern bool contain_agg_clause(Node *clause);
|
||||
extern List *pull_agg_clause(Node *clause);
|
||||
extern void count_agg_clauses(PlannerInfo *root, Node *clause,
|
||||
AggClauseCosts *costs);
|
||||
|
||||
|
||||
@@ -14,13 +14,14 @@
|
||||
#ifndef TLIST_H
|
||||
#define TLIST_H
|
||||
|
||||
#include "nodes/relation.h"
|
||||
#include "optimizer/var.h"
|
||||
|
||||
|
||||
extern TargetEntry *tlist_member(Node *node, List *targetlist);
|
||||
extern TargetEntry *tlist_member_ignore_relabel(Node *node, List *targetlist);
|
||||
|
||||
extern List *flatten_tlist(List *tlist);
|
||||
extern List *flatten_tlist(List *tlist, PVCAggregateBehavior aggbehavior,
|
||||
PVCPlaceHolderBehavior phbehavior);
|
||||
extern List *add_to_flat_tlist(List *tlist, List *exprs);
|
||||
|
||||
extern List *get_tlist_exprs(List *tlist, bool includeJunk);
|
||||
|
||||
@@ -16,11 +16,18 @@
|
||||
|
||||
#include "nodes/relation.h"
|
||||
|
||||
typedef enum
|
||||
{
|
||||
PVC_REJECT_AGGREGATES, /* throw error if Aggref found */
|
||||
PVC_INCLUDE_AGGREGATES, /* include Aggrefs in output list */
|
||||
PVC_RECURSE_AGGREGATES /* recurse into Aggref arguments */
|
||||
} PVCAggregateBehavior;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
PVC_REJECT_PLACEHOLDERS, /* throw error if PlaceHolderVar found */
|
||||
PVC_INCLUDE_PLACEHOLDERS, /* include PlaceHolderVars in output list */
|
||||
PVC_RECURSE_PLACEHOLDERS /* recurse into PlaceHolderVar argument */
|
||||
PVC_RECURSE_PLACEHOLDERS /* recurse into PlaceHolderVar arguments */
|
||||
} PVCPlaceHolderBehavior;
|
||||
|
||||
extern Relids pull_varnos(Node *node);
|
||||
@@ -30,7 +37,8 @@ extern bool contain_vars_of_level(Node *node, int levelsup);
|
||||
extern int locate_var_of_level(Node *node, int levelsup);
|
||||
extern int locate_var_of_relation(Node *node, int relid, int levelsup);
|
||||
extern int find_minimum_var_level(Node *node);
|
||||
extern List *pull_var_clause(Node *node, PVCPlaceHolderBehavior behavior);
|
||||
extern List *pull_var_clause(Node *node, PVCAggregateBehavior aggbehavior,
|
||||
PVCPlaceHolderBehavior phbehavior);
|
||||
extern Node *flatten_join_alias_vars(PlannerInfo *root, Node *node);
|
||||
|
||||
#endif /* VAR_H */
|
||||
|
||||
Reference in New Issue
Block a user