mirror of
https://github.com/postgres/postgres.git
synced 2025-08-27 07:42:10 +03:00
Centralize the logic for detecting misplaced aggregates, window funcs, etc.
Formerly we relied on checking after-the-fact to see if an expression contained aggregates, window functions, or sub-selects when it shouldn't. This is grotty, easily forgotten (indeed, we had forgotten to teach DefineIndex about rejecting window functions), and none too efficient since it requires extra traversals of the parse tree. To improve matters, define an enum type that classifies all SQL sub-expressions, store it in ParseState to show what kind of expression we are currently parsing, and make transformAggregateCall, transformWindowFuncCall, and transformSubLink check the expression type and throw error if the type indicates the construct is disallowed. This allows removal of a large number of ad-hoc checks scattered around the code base. The enum type is sufficiently fine-grained that we can still produce error messages of at least the same specificity as before. Bringing these error checks together revealed that we'd been none too consistent about phrasing of the error messages, so standardize the wording a bit. Also, rewrite checking of aggregate arguments so that it requires only one traversal of the arguments, rather than up to three as before. In passing, clean up some more comments left over from add_missing_from support, and annotate some tests that I think are dead code now that that's gone. (I didn't risk actually removing said dead code, though.)
This commit is contained in:
@@ -52,17 +52,6 @@ static Relids offset_relid_set(Relids relids, int offset);
|
||||
static Relids adjust_relid_set(Relids relids, int oldrelid, int newrelid);
|
||||
|
||||
|
||||
/*
|
||||
* checkExprHasAggs -
|
||||
* Check if an expression contains an aggregate function call of the
|
||||
* current query level.
|
||||
*/
|
||||
bool
|
||||
checkExprHasAggs(Node *node)
|
||||
{
|
||||
return contain_aggs_of_level(node, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* contain_aggs_of_level -
|
||||
* Check if an expression contains an aggregate function call of a
|
||||
@@ -185,12 +174,12 @@ locate_agg_of_level_walker(Node *node,
|
||||
}
|
||||
|
||||
/*
|
||||
* checkExprHasWindowFuncs -
|
||||
* contain_windowfuncs -
|
||||
* Check if an expression contains a window function call of the
|
||||
* current query level.
|
||||
*/
|
||||
bool
|
||||
checkExprHasWindowFuncs(Node *node)
|
||||
contain_windowfuncs(Node *node)
|
||||
{
|
||||
/*
|
||||
* Must be prepared to start with a Query or a bare expression tree; if
|
||||
@@ -1049,7 +1038,7 @@ AddQual(Query *parsetree, Node *qual)
|
||||
/*
|
||||
* We had better not have stuck an aggregate into the WHERE clause.
|
||||
*/
|
||||
Assert(!checkExprHasAggs(copy));
|
||||
Assert(!contain_aggs_of_level(copy, 0));
|
||||
|
||||
/*
|
||||
* Make sure query is marked correctly if added qual has sublinks. Need
|
||||
|
Reference in New Issue
Block a user