1996-08-28 03:59:28 +02:00
|
|
|
/*-------------------------------------------------------------------------
|
|
|
|
*
|
1999-02-14 00:22:53 +01:00
|
|
|
* nodeFuncs.h
|
2008-08-26 00:42:34 +02:00
|
|
|
* Various general-purpose manipulations of Node trees
|
1996-08-28 03:59:28 +02:00
|
|
|
*
|
2023-01-02 21:00:37 +01:00
|
|
|
* Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
|
2000-01-26 06:58:53 +01:00
|
|
|
* Portions Copyright (c) 1994, Regents of the University of California
|
1996-08-28 03:59:28 +02:00
|
|
|
*
|
2010-09-20 22:08:53 +02:00
|
|
|
* src/include/nodes/nodeFuncs.h
|
1996-08-28 03:59:28 +02:00
|
|
|
*
|
|
|
|
*-------------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
#ifndef NODEFUNCS_H
|
|
|
|
#define NODEFUNCS_H
|
|
|
|
|
2008-08-26 00:42:34 +02:00
|
|
|
#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
2022-09-21 00:03:22 +02:00
|
|
|
struct PlanState; /* avoid including execnodes.h too */
|
|
|
|
|
2008-08-26 00:42:34 +02:00
|
|
|
|
|
|
|
/* flags bits for query_tree_walker and query_tree_mutator */
|
|
|
|
#define QTW_IGNORE_RT_SUBQUERIES 0x01 /* subqueries in rtable */
|
2008-10-04 23:56:55 +02:00
|
|
|
#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 */
|
2011-03-20 01:29:08 +01:00
|
|
|
#define QTW_IGNORE_RANGE_TABLE 0x08 /* skip rangetable entirely */
|
2019-01-25 23:09:45 +01:00
|
|
|
#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 */
|
2023-05-02 05:23:08 +02:00
|
|
|
#define QTW_EXAMINE_SORTGROUP 0x80 /* include SortGroupClause lists */
|
2008-08-26 00:42:34 +02:00
|
|
|
|
2016-06-10 22:03:37 +02:00
|
|
|
/* 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
2022-09-21 00:03:22 +02:00
|
|
|
/* 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);
|
|
|
|
|
2008-08-26 00:42:34 +02:00
|
|
|
|
2011-12-07 20:46:56 +01:00
|
|
|
extern Oid exprType(const Node *expr);
|
|
|
|
extern int32 exprTypmod(const Node *expr);
|
|
|
|
extern bool exprIsLengthCoercion(const Node *expr, int32 *coercedTypmod);
|
Suppress unnecessary RelabelType nodes in yet more cases.
Commit a477bfc1d fixed eval_const_expressions() to ensure that it
didn't generate unnecessary RelabelType nodes, but I failed to notice
that some other places in the planner had the same issue. Really
noplace in the planner should be using plain makeRelabelType(), for
fear of generating expressions that should be equal() to semantically
equivalent trees, but aren't.
An example is that because canonicalize_ec_expression() failed
to be careful about this, we could end up with an equivalence class
containing both a plain Const, and a Const-with-RelabelType
representing exactly the same value. So far as I can tell this led to
no visible misbehavior, but we did waste a bunch of cycles generating
and evaluating "Const = Const-with-RelabelType" to prove such entries
are redundant.
Hence, move the support function added by a477bfc1d to where it can
be more generally useful, and use it in the places where planner code
previously used makeRelabelType.
Back-patch to v12, like the previous patch. While I have no concrete
evidence of any real misbehavior here, it's certainly possible that
I overlooked a case where equivalent expressions that aren't equal()
could cause a user-visible problem. In any case carrying extra
RelabelType nodes through planning to execution isn't very desirable.
Discussion: https://postgr.es/m/1311836.1597781384@sss.pgh.pa.us
2020-08-19 20:07:49 +02:00
|
|
|
extern Node *applyRelabelType(Node *arg, Oid rtype, int32 rtypmod, Oid rcollid,
|
|
|
|
CoercionForm rformat, int rlocation,
|
|
|
|
bool overwrite_ok);
|
2012-03-23 22:29:57 +01:00
|
|
|
extern Node *relabel_to_typmod(Node *expr, int32 typmod);
|
2013-07-24 00:21:19 +02:00
|
|
|
extern Node *strip_implicit_coercions(Node *node);
|
2008-08-26 00:42:34 +02:00
|
|
|
extern bool expression_returns_set(Node *clause);
|
|
|
|
|
2011-12-07 20:46:56 +01:00
|
|
|
extern Oid exprCollation(const Node *expr);
|
|
|
|
extern Oid exprInputCollation(const Node *expr);
|
2011-03-20 01:29:08 +01:00
|
|
|
extern void exprSetCollation(Node *expr, Oid collation);
|
|
|
|
extern void exprSetInputCollation(Node *expr, Oid inputcollation);
|
|
|
|
|
2011-12-07 20:46:56 +01:00
|
|
|
extern int exprLocation(const Node *expr);
|
2008-08-29 01:09:48 +02:00
|
|
|
|
2016-06-10 22:03:37 +02:00
|
|
|
extern void fix_opfuncids(Node *node);
|
|
|
|
extern void set_opfuncid(OpExpr *opexpr);
|
|
|
|
extern void set_sa_opfuncid(ScalarArrayOpExpr *opexpr);
|
|
|
|
|
2019-01-29 21:26:44 +01:00
|
|
|
/* 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);
|
|
|
|
}
|
|
|
|
|
2016-06-10 22:03:37 +02:00
|
|
|
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
2022-09-21 00:03:22 +02:00
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*/
|
2001-10-28 07:26:15 +01:00
|
|
|
|
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
2022-09-21 00:03:22 +02:00
|
|
|
#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,
|
2008-10-04 23:56:55 +02:00
|
|
|
void *context);
|
|
|
|
|
1996-08-28 03:59:28 +02:00
|
|
|
#endif /* NODEFUNCS_H */
|