You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
postgres/src/include/nodes/nodeFuncs.h

225 lines
7.5 KiB

/*-------------------------------------------------------------------------
*
* nodeFuncs.h
* Various general-purpose manipulations of Node trees
*
* Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* src/include/nodes/nodeFuncs.h
*
*-------------------------------------------------------------------------
*/
#ifndef NODEFUNCS_H
#define NODEFUNCS_H
#include "nodes/parsenodes.h"
Revise tree-walk APIs to improve spec compliance & silence warnings. expression_tree_walker and allied functions have traditionally declared their callback functions as, say, "bool (*walker) ()" to allow for variation in the declared types of the callback functions' context argument. This is apparently going to be forbidden by the next version of the C standard, and the latest version of clang warns about that. In any case it's always been pretty poor for error-detection purposes, so fixing it is a good thing to do. What we want to do is change the callback argument declarations to be like "bool (*walker) (Node *node, void *context)", which is correct so far as expression_tree_walker and friends are concerned, but not change the actual callback functions. Strict compliance with the C standard would require changing them to declare their arguments as "void *context" and then cast to the appropriate context struct type internally. That'd be very invasive and it would also introduce a bunch of opportunities for future bugs, since we'd no longer have any check that the correct sort of context object is passed by outside callers or internal recursion cases. Therefore, we're just going to ignore the standard's position that "void *" isn't necessarily compatible with struct pointers. No machine built in the last forty or so years actually behaves that way, so it's not worth introducing bug hazards for compatibility with long-dead hardware. Therefore, to silence these compiler warnings, introduce a layer of macro wrappers that cast the supplied function name to the official argument type. Thanks to our use of -Wcast-function-type, this will still produce a warning if the supplied function is seriously incompatible with the required signature, without going as far as the official spec restriction does. This method fixes the problem without any need for source code changes outside nodeFuncs.h/.c. However, it is an ABI break because the physically called functions now have names ending in "_impl". Hence we can only fix it this way in HEAD. In the back branches, we'll have to settle for disabling -Wdeprecated-non-prototype. Discussion: https://postgr.es/m/CA+hUKGKpHPDTv67Y+s6yiC8KH5OXeDg6a-twWo_xznKTcG0kSA@mail.gmail.com
3 years ago
struct PlanState; /* avoid including execnodes.h too */
/* flags bits for query_tree_walker and query_tree_mutator */
Phase 2 of pgindent updates. Change pg_bsd_indent to follow upstream rules for placement of comments to the right of code, and remove pgindent hack that caused comments following #endif to not obey the general rule. Commit e3860ffa4dd0dad0dd9eea4be9cc1412373a8c89 wasn't actually using the published version of pg_bsd_indent, but a hacked-up version that tried to minimize the amount of movement of comments to the right of code. The situation of interest is where such a comment has to be moved to the right of its default placement at column 33 because there's code there. BSD indent has always moved right in units of tab stops in such cases --- but in the previous incarnation, indent was working in 8-space tab stops, while now it knows we use 4-space tabs. So the net result is that in about half the cases, such comments are placed one tab stop left of before. This is better all around: it leaves more room on the line for comment text, and it means that in such cases the comment uniformly starts at the next 4-space tab stop after the code, rather than sometimes one and sometimes two tabs after. Also, ensure that comments following #endif are indented the same as comments following other preprocessor commands such as #else. That inconsistency turns out to have been self-inflicted damage from a poorly-thought-through post-indent "fixup" in pgindent. This patch is much less interesting than the first round of indent changes, but also bulkier, so I thought it best to separate the effects. Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
9 years ago
#define QTW_IGNORE_RT_SUBQUERIES 0x01 /* subqueries in rtable */
#define QTW_IGNORE_CTE_SUBQUERIES 0x02 /* subqueries in cteList */
#define QTW_IGNORE_RC_SUBQUERIES 0x03 /* both of above */
#define QTW_IGNORE_JOINALIASES 0x04 /* JOIN alias var lists */
#define QTW_IGNORE_RANGE_TABLE 0x08 /* skip rangetable entirely */
#define QTW_EXAMINE_RTES_BEFORE 0x10 /* examine RTE nodes before their
* contents */
#define QTW_EXAMINE_RTES_AFTER 0x20 /* examine RTE nodes after their
* contents */
#define QTW_DONT_COPY_QUERY 0x40 /* do not copy top Query */
#define QTW_EXAMINE_SORTGROUP 0x80 /* include SortGroupClause lists */
Introduce an RTE for the grouping step If there are subqueries in the grouping expressions, each of these subqueries in the targetlist and HAVING clause is expanded into distinct SubPlan nodes. As a result, only one of these SubPlan nodes would be converted to reference to the grouping key column output by the Agg node; others would have to get evaluated afresh. This is not efficient, and with grouping sets this can cause wrong results issues in cases where they should go to NULL because they are from the wrong grouping set. Furthermore, during re-evaluation, these SubPlan nodes might use nulled column values from grouping sets, which is not correct. This issue is not limited to subqueries. For other types of expressions that are part of grouping items, if they are transformed into another form during preprocessing, they may fail to match lower target items. This can also lead to wrong results with grouping sets. To fix this issue, we introduce a new kind of RTE representing the output of the grouping step, with columns that are the Vars or expressions being grouped on. In the parser, we replace the grouping expressions in the targetlist and HAVING clause with Vars referencing this new RTE, so that the output of the parser directly expresses the semantic requirement that the grouping expressions be gotten from the grouping output rather than computed some other way. In the planner, we first preprocess all the columns of this new RTE and then replace any Vars in the targetlist and HAVING clause that reference this new RTE with the underlying grouping expressions, so that we will have only one instance of a SubPlan node for each subquery contained in the grouping expressions. Bump catversion because this changes the querytree produced by the parser. Thanks to Tom Lane for the idea to invent a new kind of RTE. Per reports from Geoff Winkless, Tobias Wendorff, Richard Guo from various threads. Author: Richard Guo Reviewed-by: Ashutosh Bapat, Sutou Kouhei Discussion: https://postgr.es/m/CAMbWs4_dp7e7oTwaiZeBX8+P1rXw4ThkZxh1QG81rhu9Z47VsQ@mail.gmail.com
1 year ago
#define QTW_IGNORE_GROUPEXPRS 0x100 /* GROUP expressions list */
/* callback function for check_functions_in_node */
typedef bool (*check_function_callback) (Oid func_id, void *context);
Revise tree-walk APIs to improve spec compliance & silence warnings. expression_tree_walker and allied functions have traditionally declared their callback functions as, say, "bool (*walker) ()" to allow for variation in the declared types of the callback functions' context argument. This is apparently going to be forbidden by the next version of the C standard, and the latest version of clang warns about that. In any case it's always been pretty poor for error-detection purposes, so fixing it is a good thing to do. What we want to do is change the callback argument declarations to be like "bool (*walker) (Node *node, void *context)", which is correct so far as expression_tree_walker and friends are concerned, but not change the actual callback functions. Strict compliance with the C standard would require changing them to declare their arguments as "void *context" and then cast to the appropriate context struct type internally. That'd be very invasive and it would also introduce a bunch of opportunities for future bugs, since we'd no longer have any check that the correct sort of context object is passed by outside callers or internal recursion cases. Therefore, we're just going to ignore the standard's position that "void *" isn't necessarily compatible with struct pointers. No machine built in the last forty or so years actually behaves that way, so it's not worth introducing bug hazards for compatibility with long-dead hardware. Therefore, to silence these compiler warnings, introduce a layer of macro wrappers that cast the supplied function name to the official argument type. Thanks to our use of -Wcast-function-type, this will still produce a warning if the supplied function is seriously incompatible with the required signature, without going as far as the official spec restriction does. This method fixes the problem without any need for source code changes outside nodeFuncs.h/.c. However, it is an ABI break because the physically called functions now have names ending in "_impl". Hence we can only fix it this way in HEAD. In the back branches, we'll have to settle for disabling -Wdeprecated-non-prototype. Discussion: https://postgr.es/m/CA+hUKGKpHPDTv67Y+s6yiC8KH5OXeDg6a-twWo_xznKTcG0kSA@mail.gmail.com
3 years ago
/* callback functions for tree walkers */
typedef bool (*tree_walker_callback) (Node *node, void *context);
typedef bool (*planstate_tree_walker_callback) (struct PlanState *planstate,
void *context);
/* callback functions for tree mutators */
typedef Node *(*tree_mutator_callback) (Node *node, void *context);
extern Oid exprType(const Node *expr);
extern int32 exprTypmod(const Node *expr);
extern bool exprIsLengthCoercion(const Node *expr, int32 *coercedTypmod);
extern Node *applyRelabelType(Node *arg, Oid rtype, int32 rtypmod, Oid rcollid,
CoercionForm rformat, int rlocation,
bool overwrite_ok);
extern Node *relabel_to_typmod(Node *expr, int32 typmod);
extern Node *strip_implicit_coercions(Node *node);
extern bool expression_returns_set(Node *clause);
extern Oid exprCollation(const Node *expr);
extern Oid exprInputCollation(const Node *expr);
extern void exprSetCollation(Node *expr, Oid collation);
extern void exprSetInputCollation(Node *expr, Oid inputcollation);
extern int exprLocation(const Node *expr);
extern void fix_opfuncids(Node *node);
extern void set_opfuncid(OpExpr *opexpr);
extern void set_sa_opfuncid(ScalarArrayOpExpr *opexpr);
/* Is clause a FuncExpr clause? */
static inline bool
is_funcclause(const void *clause)
{
return clause != NULL && IsA(clause, FuncExpr);
}
/* Is clause an OpExpr clause? */
static inline bool
is_opclause(const void *clause)
{
return clause != NULL && IsA(clause, OpExpr);
}
/* Extract left arg of a binary opclause, or only arg of a unary opclause */
static inline Node *
get_leftop(const void *clause)
{
const OpExpr *expr = (const OpExpr *) clause;
if (expr->args != NIL)
return (Node *) linitial(expr->args);
else
return NULL;
}
/* Extract right arg of a binary opclause (NULL if it's a unary opclause) */
static inline Node *
get_rightop(const void *clause)
{
const OpExpr *expr = (const OpExpr *) clause;
if (list_length(expr->args) >= 2)
return (Node *) lsecond(expr->args);
else
return NULL;
}
/* Is clause an AND clause? */
static inline bool
is_andclause(const void *clause)
{
return (clause != NULL &&
IsA(clause, BoolExpr) &&
((const BoolExpr *) clause)->boolop == AND_EXPR);
}
/* Is clause an OR clause? */
static inline bool
is_orclause(const void *clause)
{
return (clause != NULL &&
IsA(clause, BoolExpr) &&
((const BoolExpr *) clause)->boolop == OR_EXPR);
}
/* Is clause a NOT clause? */
static inline bool
is_notclause(const void *clause)
{
return (clause != NULL &&
IsA(clause, BoolExpr) &&
((const BoolExpr *) clause)->boolop == NOT_EXPR);
}
/* Extract argument from a clause known to be a NOT clause */
static inline Expr *
get_notclausearg(const void *notclause)
{
return (Expr *) linitial(((const BoolExpr *) notclause)->args);
}
extern bool check_functions_in_node(Node *node, check_function_callback checker,
void *context);
Revise tree-walk APIs to improve spec compliance & silence warnings. expression_tree_walker and allied functions have traditionally declared their callback functions as, say, "bool (*walker) ()" to allow for variation in the declared types of the callback functions' context argument. This is apparently going to be forbidden by the next version of the C standard, and the latest version of clang warns about that. In any case it's always been pretty poor for error-detection purposes, so fixing it is a good thing to do. What we want to do is change the callback argument declarations to be like "bool (*walker) (Node *node, void *context)", which is correct so far as expression_tree_walker and friends are concerned, but not change the actual callback functions. Strict compliance with the C standard would require changing them to declare their arguments as "void *context" and then cast to the appropriate context struct type internally. That'd be very invasive and it would also introduce a bunch of opportunities for future bugs, since we'd no longer have any check that the correct sort of context object is passed by outside callers or internal recursion cases. Therefore, we're just going to ignore the standard's position that "void *" isn't necessarily compatible with struct pointers. No machine built in the last forty or so years actually behaves that way, so it's not worth introducing bug hazards for compatibility with long-dead hardware. Therefore, to silence these compiler warnings, introduce a layer of macro wrappers that cast the supplied function name to the official argument type. Thanks to our use of -Wcast-function-type, this will still produce a warning if the supplied function is seriously incompatible with the required signature, without going as far as the official spec restriction does. This method fixes the problem without any need for source code changes outside nodeFuncs.h/.c. However, it is an ABI break because the physically called functions now have names ending in "_impl". Hence we can only fix it this way in HEAD. In the back branches, we'll have to settle for disabling -Wdeprecated-non-prototype. Discussion: https://postgr.es/m/CA+hUKGKpHPDTv67Y+s6yiC8KH5OXeDg6a-twWo_xznKTcG0kSA@mail.gmail.com
3 years ago
/*
* The following functions are usually passed walker or mutator callbacks
* that are declared like "bool walker(Node *node, my_struct *context)"
* rather than "bool walker(Node *node, void *context)" as a strict reading
* of the C standard would require. Changing the callbacks' declarations
* to "void *" would create serious hazards of passing them the wrong context
* struct type, so we respectfully decline to support the standard's position
* that a pointer to struct is incompatible with "void *". Instead, silence
* related compiler warnings by inserting casts into these macro wrappers.
*/
Revise tree-walk APIs to improve spec compliance & silence warnings. expression_tree_walker and allied functions have traditionally declared their callback functions as, say, "bool (*walker) ()" to allow for variation in the declared types of the callback functions' context argument. This is apparently going to be forbidden by the next version of the C standard, and the latest version of clang warns about that. In any case it's always been pretty poor for error-detection purposes, so fixing it is a good thing to do. What we want to do is change the callback argument declarations to be like "bool (*walker) (Node *node, void *context)", which is correct so far as expression_tree_walker and friends are concerned, but not change the actual callback functions. Strict compliance with the C standard would require changing them to declare their arguments as "void *context" and then cast to the appropriate context struct type internally. That'd be very invasive and it would also introduce a bunch of opportunities for future bugs, since we'd no longer have any check that the correct sort of context object is passed by outside callers or internal recursion cases. Therefore, we're just going to ignore the standard's position that "void *" isn't necessarily compatible with struct pointers. No machine built in the last forty or so years actually behaves that way, so it's not worth introducing bug hazards for compatibility with long-dead hardware. Therefore, to silence these compiler warnings, introduce a layer of macro wrappers that cast the supplied function name to the official argument type. Thanks to our use of -Wcast-function-type, this will still produce a warning if the supplied function is seriously incompatible with the required signature, without going as far as the official spec restriction does. This method fixes the problem without any need for source code changes outside nodeFuncs.h/.c. However, it is an ABI break because the physically called functions now have names ending in "_impl". Hence we can only fix it this way in HEAD. In the back branches, we'll have to settle for disabling -Wdeprecated-non-prototype. Discussion: https://postgr.es/m/CA+hUKGKpHPDTv67Y+s6yiC8KH5OXeDg6a-twWo_xznKTcG0kSA@mail.gmail.com
3 years ago
#define expression_tree_walker(n, w, c) \
expression_tree_walker_impl(n, (tree_walker_callback) (w), c)
#define expression_tree_mutator(n, m, c) \
expression_tree_mutator_impl(n, (tree_mutator_callback) (m), c)
#define query_tree_walker(q, w, c, f) \
query_tree_walker_impl(q, (tree_walker_callback) (w), c, f)
#define query_tree_mutator(q, m, c, f) \
query_tree_mutator_impl(q, (tree_mutator_callback) (m), c, f)
#define range_table_walker(rt, w, c, f) \
range_table_walker_impl(rt, (tree_walker_callback) (w), c, f)
#define range_table_mutator(rt, m, c, f) \
range_table_mutator_impl(rt, (tree_mutator_callback) (m), c, f)
#define range_table_entry_walker(r, w, c, f) \
range_table_entry_walker_impl(r, (tree_walker_callback) (w), c, f)
#define query_or_expression_tree_walker(n, w, c, f) \
query_or_expression_tree_walker_impl(n, (tree_walker_callback) (w), c, f)
#define query_or_expression_tree_mutator(n, m, c, f) \
query_or_expression_tree_mutator_impl(n, (tree_mutator_callback) (m), c, f)
#define raw_expression_tree_walker(n, w, c) \
raw_expression_tree_walker_impl(n, (tree_walker_callback) (w), c)
#define planstate_tree_walker(ps, w, c) \
planstate_tree_walker_impl(ps, (planstate_tree_walker_callback) (w), c)
extern bool expression_tree_walker_impl(Node *node,
tree_walker_callback walker,
void *context);
extern Node *expression_tree_mutator_impl(Node *node,
tree_mutator_callback mutator,
void *context);
extern bool query_tree_walker_impl(Query *query,
tree_walker_callback walker,
void *context, int flags);
extern Query *query_tree_mutator_impl(Query *query,
tree_mutator_callback mutator,
void *context, int flags);
extern bool range_table_walker_impl(List *rtable,
tree_walker_callback walker,
void *context, int flags);
extern List *range_table_mutator_impl(List *rtable,
tree_mutator_callback mutator,
void *context, int flags);
extern bool range_table_entry_walker_impl(RangeTblEntry *rte,
tree_walker_callback walker,
void *context, int flags);
extern bool query_or_expression_tree_walker_impl(Node *node,
tree_walker_callback walker,
void *context, int flags);
extern Node *query_or_expression_tree_mutator_impl(Node *node,
tree_mutator_callback mutator,
void *context, int flags);
extern bool raw_expression_tree_walker_impl(Node *node,
tree_walker_callback walker,
void *context);
extern bool planstate_tree_walker_impl(struct PlanState *planstate,
planstate_tree_walker_callback walker,
9 years ago
void *context);
Phase 2 of pgindent updates. Change pg_bsd_indent to follow upstream rules for placement of comments to the right of code, and remove pgindent hack that caused comments following #endif to not obey the general rule. Commit e3860ffa4dd0dad0dd9eea4be9cc1412373a8c89 wasn't actually using the published version of pg_bsd_indent, but a hacked-up version that tried to minimize the amount of movement of comments to the right of code. The situation of interest is where such a comment has to be moved to the right of its default placement at column 33 because there's code there. BSD indent has always moved right in units of tab stops in such cases --- but in the previous incarnation, indent was working in 8-space tab stops, while now it knows we use 4-space tabs. So the net result is that in about half the cases, such comments are placed one tab stop left of before. This is better all around: it leaves more room on the line for comment text, and it means that in such cases the comment uniformly starts at the next 4-space tab stop after the code, rather than sometimes one and sometimes two tabs after. Also, ensure that comments following #endif are indented the same as comments following other preprocessor commands such as #else. That inconsistency turns out to have been self-inflicted damage from a poorly-thought-through post-indent "fixup" in pgindent. This patch is much less interesting than the first round of indent changes, but also bulkier, so I thought it best to separate the effects. Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
9 years ago
#endif /* NODEFUNCS_H */