PostgreSQL/src/include/rewrite/rewriteManip.h
Tom Lane eaccfded98 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.)
2012-08-10 11:36:15 -04:00

78 lines
2.7 KiB
C

/*-------------------------------------------------------------------------
*
* rewriteManip.h
* Querytree manipulation subroutines for query rewriter.
*
*
* Portions Copyright (c) 1996-2012, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* src/include/rewrite/rewriteManip.h
*
*-------------------------------------------------------------------------
*/
#ifndef REWRITEMANIP_H
#define REWRITEMANIP_H
#include "nodes/parsenodes.h"
typedef struct replace_rte_variables_context replace_rte_variables_context;
typedef Node *(*replace_rte_variables_callback) (Var *var,
replace_rte_variables_context *context);
struct replace_rte_variables_context
{
replace_rte_variables_callback callback; /* callback function */
void *callback_arg; /* context data for callback function */
int target_varno; /* RTE index to search for */
int sublevels_up; /* (current) nesting depth */
bool inserted_sublink; /* have we inserted a SubLink? */
};
extern void OffsetVarNodes(Node *node, int offset, int sublevels_up);
extern void ChangeVarNodes(Node *node, int old_varno, int new_varno,
int sublevels_up);
extern void IncrementVarSublevelsUp(Node *node, int delta_sublevels_up,
int min_sublevels_up);
extern void IncrementVarSublevelsUp_rtable(List *rtable,
int delta_sublevels_up, int min_sublevels_up);
extern bool rangeTableEntry_used(Node *node, int rt_index,
int sublevels_up);
extern bool attribute_used(Node *node, int rt_index, int attno,
int sublevels_up);
extern Query *getInsertSelectQuery(Query *parsetree, Query ***subquery_ptr);
extern void AddQual(Query *parsetree, Node *qual);
extern void AddInvertedQual(Query *parsetree, Node *qual);
extern bool contain_aggs_of_level(Node *node, int levelsup);
extern int locate_agg_of_level(Node *node, int levelsup);
extern bool contain_windowfuncs(Node *node);
extern int locate_windowfunc(Node *node);
extern bool checkExprHasSubLink(Node *node);
extern Node *replace_rte_variables(Node *node,
int target_varno, int sublevels_up,
replace_rte_variables_callback callback,
void *callback_arg,
bool *outer_hasSubLinks);
extern Node *replace_rte_variables_mutator(Node *node,
replace_rte_variables_context *context);
extern Node *map_variable_attnos(Node *node,
int target_varno, int sublevels_up,
const AttrNumber *attno_map, int map_length,
bool *found_whole_row);
extern Node *ResolveNew(Node *node, int target_varno, int sublevels_up,
RangeTblEntry *target_rte,
List *targetlist, int event, int update_varno,
bool *outer_hasSubLinks);
#endif /* REWRITEMANIP_H */