mirror of
https://github.com/postgres/postgres.git
synced 2025-06-27 23:21:58 +03:00
Adjust API of expression_tree_mutator and query_tree_mutator to
simplify callers. It turns out the common case is that the caller does want to recurse into sub-queries, so push support for that into these subroutines.
This commit is contained in:
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/subselect.c,v 1.66 2003/01/13 18:10:53 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/subselect.c,v 1.67 2003/01/17 02:01:11 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -628,12 +628,12 @@ process_sublinks_mutator(Node *node, bool *isTopQual)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Note that we will never see a SubPlan expression in the input
|
* We should never see a SubPlan expression in the input (since this is
|
||||||
* (since this is the very routine that creates 'em to begin with). So
|
* the very routine that creates 'em to begin with). We shouldn't find
|
||||||
* the code in expression_tree_mutator() that might do inappropriate
|
* ourselves invoked directly on a Query, either.
|
||||||
* things with SubPlans or SubLinks will not be exercised.
|
|
||||||
*/
|
*/
|
||||||
Assert(!is_subplan(node));
|
Assert(!is_subplan(node));
|
||||||
|
Assert(!IsA(node, Query));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we recurse down through anything other than a List node, we are
|
* If we recurse down through anything other than a List node, we are
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/prep/prepunion.c,v 1.86 2003/01/15 19:35:44 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/optimizer/prep/prepunion.c,v 1.87 2003/01/17 02:01:16 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -34,11 +34,6 @@
|
|||||||
#include "parser/parsetree.h"
|
#include "parser/parsetree.h"
|
||||||
#include "utils/lsyscache.h"
|
#include "utils/lsyscache.h"
|
||||||
|
|
||||||
/* macros borrowed from expression_tree_mutator */
|
|
||||||
|
|
||||||
#define FLATCOPY(newnode, node, nodetype) \
|
|
||||||
( (newnode) = makeNode(nodetype), \
|
|
||||||
memcpy((newnode), (node), sizeof(nodetype)) )
|
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
@ -765,12 +760,12 @@ adjust_inherited_attrs(Node *node,
|
|||||||
*/
|
*/
|
||||||
if (node && IsA(node, Query))
|
if (node && IsA(node, Query))
|
||||||
{
|
{
|
||||||
Query *query = (Query *) node;
|
|
||||||
Query *newnode;
|
Query *newnode;
|
||||||
|
|
||||||
FLATCOPY(newnode, query, Query);
|
newnode = query_tree_mutator((Query *) node,
|
||||||
query_tree_mutator(newnode, adjust_inherited_attrs_mutator,
|
adjust_inherited_attrs_mutator,
|
||||||
(void *) &context, QTW_IGNORE_SUBQUERIES);
|
(void *) &context,
|
||||||
|
QTW_IGNORE_RT_SUBQUERIES);
|
||||||
if (newnode->resultRelation == old_rt_index)
|
if (newnode->resultRelation == old_rt_index)
|
||||||
{
|
{
|
||||||
newnode->resultRelation = new_rt_index;
|
newnode->resultRelation = new_rt_index;
|
||||||
@ -899,6 +894,7 @@ adjust_inherited_attrs_mutator(Node *node,
|
|||||||
* already have been converted to subplans before we see them.
|
* already have been converted to subplans before we see them.
|
||||||
*/
|
*/
|
||||||
Assert(!IsA(node, SubLink));
|
Assert(!IsA(node, SubLink));
|
||||||
|
Assert(!IsA(node, Query));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* BUT: although we don't need to recurse into subplans, we do need to
|
* BUT: although we don't need to recurse into subplans, we do need to
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.122 2003/01/15 19:35:44 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.123 2003/01/17 02:01:16 tgl Exp $
|
||||||
*
|
*
|
||||||
* HISTORY
|
* HISTORY
|
||||||
* AUTHOR DATE MAJOR EVENT
|
* AUTHOR DATE MAJOR EVENT
|
||||||
@ -2153,7 +2153,7 @@ substitute_actual_parameters_mutator(Node *node,
|
|||||||
* {
|
* {
|
||||||
* adjust context for subquery;
|
* adjust context for subquery;
|
||||||
* result = query_tree_walker((Query *) node, my_walker, context,
|
* result = query_tree_walker((Query *) node, my_walker, context,
|
||||||
* 0); // to visit rtable items too
|
* 0); // adjust flags as needed
|
||||||
* restore context if needed;
|
* restore context if needed;
|
||||||
* return result;
|
* return result;
|
||||||
* }
|
* }
|
||||||
@ -2414,7 +2414,7 @@ query_tree_walker(Query *query,
|
|||||||
/* nothing to do */
|
/* nothing to do */
|
||||||
break;
|
break;
|
||||||
case RTE_SUBQUERY:
|
case RTE_SUBQUERY:
|
||||||
if (! (flags & QTW_IGNORE_SUBQUERIES))
|
if (! (flags & QTW_IGNORE_RT_SUBQUERIES))
|
||||||
if (walker(rte->subquery, context))
|
if (walker(rte->subquery, context))
|
||||||
return true;
|
return true;
|
||||||
break;
|
break;
|
||||||
@ -2477,17 +2477,22 @@ query_tree_walker(Query *query,
|
|||||||
* expression_tree_mutator include all those normally found in target lists
|
* expression_tree_mutator include all those normally found in target lists
|
||||||
* and qualifier clauses during the planning stage.
|
* and qualifier clauses during the planning stage.
|
||||||
*
|
*
|
||||||
|
* expression_tree_mutator will handle SubLink nodes by recursing normally
|
||||||
|
* into the "lefthand" arguments (which are expressions belonging to the outer
|
||||||
|
* plan). It will also call the mutator on the sub-Query node; however, when
|
||||||
|
* expression_tree_mutator itself is called on a Query node, it does nothing
|
||||||
|
* and returns the unmodified Query node. The net effect is that unless the
|
||||||
|
* mutator does something special at a Query node, sub-selects will not be
|
||||||
|
* visited or modified; the original sub-select will be linked to by the new
|
||||||
|
* SubLink node. Mutators that want to descend into sub-selects will usually
|
||||||
|
* do so by recognizing Query nodes and calling query_tree_mutator (below).
|
||||||
|
*
|
||||||
* expression_tree_mutator will handle a SubPlan node by recursing into
|
* expression_tree_mutator will handle a SubPlan node by recursing into
|
||||||
* the "exprs" and "args" lists (which belong to the outer plan), but it
|
* the "exprs" and "args" lists (which belong to the outer plan), but it
|
||||||
* will simply copy the link to the inner plan, since that's typically what
|
* will simply copy the link to the inner plan, since that's typically what
|
||||||
* expression tree mutators want. A mutator that wants to modify the subplan
|
* expression tree mutators want. A mutator that wants to modify the subplan
|
||||||
* can force appropriate behavior by recognizing SubPlan expression nodes
|
* can force appropriate behavior by recognizing SubPlan expression nodes
|
||||||
* and doing the right thing.
|
* and doing the right thing.
|
||||||
*
|
|
||||||
* SubLink nodes are handled by recursing into the "lefthand" argument list
|
|
||||||
* only. (A SubLink will be seen only if the tree has not yet been
|
|
||||||
* processed by subselect.c.) Again, this can be overridden by the mutator,
|
|
||||||
* but it seems to be the most useful default behavior.
|
|
||||||
*--------------------
|
*--------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -2593,14 +2598,16 @@ expression_tree_mutator(Node *node,
|
|||||||
break;
|
break;
|
||||||
case T_SubLink:
|
case T_SubLink:
|
||||||
{
|
{
|
||||||
/*
|
|
||||||
* We transform the lefthand side, but not the subquery.
|
|
||||||
*/
|
|
||||||
SubLink *sublink = (SubLink *) node;
|
SubLink *sublink = (SubLink *) node;
|
||||||
SubLink *newnode;
|
SubLink *newnode;
|
||||||
|
|
||||||
FLATCOPY(newnode, sublink, SubLink);
|
FLATCOPY(newnode, sublink, SubLink);
|
||||||
MUTATE(newnode->lefthand, sublink->lefthand, List *);
|
MUTATE(newnode->lefthand, sublink->lefthand, List *);
|
||||||
|
/*
|
||||||
|
* Also invoke the mutator on the sublink's Query node, so
|
||||||
|
* it can recurse into the sub-query if it wants to.
|
||||||
|
*/
|
||||||
|
MUTATE(newnode->subselect, sublink->subselect, Node *);
|
||||||
return (Node *) newnode;
|
return (Node *) newnode;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -2707,6 +2714,9 @@ expression_tree_mutator(Node *node,
|
|||||||
return (Node *) newnode;
|
return (Node *) newnode;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case T_Query:
|
||||||
|
/* Do nothing with a sub-Query, per discussion above */
|
||||||
|
return node;
|
||||||
case T_List:
|
case T_List:
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@ -2781,17 +2791,17 @@ expression_tree_mutator(Node *node,
|
|||||||
* mutator intends to descend into subqueries. It is also useful for
|
* mutator intends to descend into subqueries. It is also useful for
|
||||||
* descending into subqueries within a mutator.
|
* descending into subqueries within a mutator.
|
||||||
*
|
*
|
||||||
* The specified Query node is modified-in-place; do a FLATCOPY() beforehand
|
* Some callers want to suppress mutating of certain items in the Query,
|
||||||
* if you don't want to change the original. All substructure is safely
|
|
||||||
* copied, however.
|
|
||||||
*
|
|
||||||
* Some callers want to suppress mutating of certain items in the sub-Query,
|
|
||||||
* typically because they need to process them specially, or don't actually
|
* typically because they need to process them specially, or don't actually
|
||||||
* want to recurse into subqueries. This is supported by the flags argument,
|
* want to recurse into subqueries. This is supported by the flags argument,
|
||||||
* which is the bitwise OR of flag values to suppress mutating of
|
* which is the bitwise OR of flag values to suppress mutating of
|
||||||
* indicated items. (More flag bits may be added as needed.)
|
* indicated items. (More flag bits may be added as needed.)
|
||||||
|
*
|
||||||
|
* Normally the Query node itself is copied, but some callers want it to be
|
||||||
|
* modified in-place; they must pass QTW_DONT_COPY_QUERY in flags. All
|
||||||
|
* modified substructure is safely copied in any case.
|
||||||
*/
|
*/
|
||||||
void
|
Query *
|
||||||
query_tree_mutator(Query *query,
|
query_tree_mutator(Query *query,
|
||||||
Node *(*mutator) (),
|
Node *(*mutator) (),
|
||||||
void *context,
|
void *context,
|
||||||
@ -2802,6 +2812,14 @@ query_tree_mutator(Query *query,
|
|||||||
|
|
||||||
Assert(query != NULL && IsA(query, Query));
|
Assert(query != NULL && IsA(query, Query));
|
||||||
|
|
||||||
|
if (! (flags & QTW_DONT_COPY_QUERY))
|
||||||
|
{
|
||||||
|
Query *newquery;
|
||||||
|
|
||||||
|
FLATCOPY(newquery, query, Query);
|
||||||
|
query = newquery;
|
||||||
|
}
|
||||||
|
|
||||||
MUTATE(query->targetList, query->targetList, List *);
|
MUTATE(query->targetList, query->targetList, List *);
|
||||||
MUTATE(query->jointree, query->jointree, FromExpr *);
|
MUTATE(query->jointree, query->jointree, FromExpr *);
|
||||||
MUTATE(query->setOperations, query->setOperations, Node *);
|
MUTATE(query->setOperations, query->setOperations, Node *);
|
||||||
@ -2818,7 +2836,7 @@ query_tree_mutator(Query *query,
|
|||||||
/* nothing to do, don't bother to make a copy */
|
/* nothing to do, don't bother to make a copy */
|
||||||
break;
|
break;
|
||||||
case RTE_SUBQUERY:
|
case RTE_SUBQUERY:
|
||||||
if (! (flags & QTW_IGNORE_SUBQUERIES))
|
if (! (flags & QTW_IGNORE_RT_SUBQUERIES))
|
||||||
{
|
{
|
||||||
FLATCOPY(newrte, rte, RangeTblEntry);
|
FLATCOPY(newrte, rte, RangeTblEntry);
|
||||||
CHECKFLATCOPY(newrte->subquery, rte->subquery, Query);
|
CHECKFLATCOPY(newrte->subquery, rte->subquery, Query);
|
||||||
@ -2843,4 +2861,51 @@ query_tree_mutator(Query *query,
|
|||||||
newrt = lappend(newrt, rte);
|
newrt = lappend(newrt, rte);
|
||||||
}
|
}
|
||||||
query->rtable = newrt;
|
query->rtable = newrt;
|
||||||
|
return query;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* query_or_expression_tree_walker --- hybrid form
|
||||||
|
*
|
||||||
|
* This routine will invoke query_tree_walker if called on a Query node,
|
||||||
|
* else will invoke the walker directly. This is a useful way of starting
|
||||||
|
* the recursion when the walker's normal change of state is not appropriate
|
||||||
|
* for the outermost Query node.
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
query_or_expression_tree_walker(Node *node,
|
||||||
|
bool (*walker) (),
|
||||||
|
void *context,
|
||||||
|
int flags)
|
||||||
|
{
|
||||||
|
if (node && IsA(node, Query))
|
||||||
|
return query_tree_walker((Query *) node,
|
||||||
|
walker,
|
||||||
|
context,
|
||||||
|
flags);
|
||||||
|
else
|
||||||
|
return walker(node, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* query_or_expression_tree_mutator --- hybrid form
|
||||||
|
*
|
||||||
|
* This routine will invoke query_tree_mutator if called on a Query node,
|
||||||
|
* else will invoke the mutator directly. This is a useful way of starting
|
||||||
|
* the recursion when the mutator's normal change of state is not appropriate
|
||||||
|
* for the outermost Query node.
|
||||||
|
*/
|
||||||
|
Node *
|
||||||
|
query_or_expression_tree_mutator(Node *node,
|
||||||
|
Node *(*mutator) (),
|
||||||
|
void *context,
|
||||||
|
int flags)
|
||||||
|
{
|
||||||
|
if (node && IsA(node, Query))
|
||||||
|
return (Node *) query_tree_mutator((Query *) node,
|
||||||
|
mutator,
|
||||||
|
context,
|
||||||
|
flags);
|
||||||
|
else
|
||||||
|
return mutator(node, context);
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/var.c,v 1.45 2003/01/16 18:26:02 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/var.c,v 1.46 2003/01/17 02:01:16 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -20,16 +20,6 @@
|
|||||||
#include "parser/parsetree.h"
|
#include "parser/parsetree.h"
|
||||||
|
|
||||||
|
|
||||||
/* macros borrowed from expression_tree_mutator */
|
|
||||||
|
|
||||||
#define FLATCOPY(newnode, node, nodetype) \
|
|
||||||
( (newnode) = makeNode(nodetype), \
|
|
||||||
memcpy((newnode), (node), sizeof(nodetype)) )
|
|
||||||
|
|
||||||
#define MUTATE(newfield, oldfield, fieldtype, mutator, context) \
|
|
||||||
( (newfield) = (fieldtype) mutator((Node *) (oldfield), (context)) )
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
List *varlist;
|
List *varlist;
|
||||||
@ -87,14 +77,12 @@ pull_varnos(Node *node)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Must be prepared to start with a Query or a bare expression tree;
|
* Must be prepared to start with a Query or a bare expression tree;
|
||||||
* if it's a Query, go straight to query_tree_walker to make sure that
|
* if it's a Query, we don't want to increment sublevels_up.
|
||||||
* sublevels_up doesn't get incremented prematurely.
|
|
||||||
*/
|
*/
|
||||||
if (node && IsA(node, Query))
|
query_or_expression_tree_walker(node,
|
||||||
query_tree_walker((Query *) node, pull_varnos_walker,
|
pull_varnos_walker,
|
||||||
(void *) &context, 0);
|
(void *) &context,
|
||||||
else
|
0);
|
||||||
pull_varnos_walker(node, &context);
|
|
||||||
|
|
||||||
return context.varlist;
|
return context.varlist;
|
||||||
}
|
}
|
||||||
@ -113,24 +101,6 @@ pull_varnos_walker(Node *node, pull_varnos_context *context)
|
|||||||
context->varlist = lconsi(var->varno, context->varlist);
|
context->varlist = lconsi(var->varno, context->varlist);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (is_subplan(node))
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* Already-planned subquery. Examine the args list (parameters to
|
|
||||||
* be passed to subquery), as well as the exprs list which is
|
|
||||||
* executed by the outer query. But short-circuit recursion into
|
|
||||||
* the subquery itself, which would be a waste of effort.
|
|
||||||
*/
|
|
||||||
SubPlan *subplan = (SubPlan *) node;
|
|
||||||
|
|
||||||
if (pull_varnos_walker((Node *) subplan->exprs,
|
|
||||||
context))
|
|
||||||
return true;
|
|
||||||
if (pull_varnos_walker((Node *) subplan->args,
|
|
||||||
context))
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (IsA(node, Query))
|
if (IsA(node, Query))
|
||||||
{
|
{
|
||||||
/* Recurse into RTE subquery or not-yet-planned sublink subquery */
|
/* Recurse into RTE subquery or not-yet-planned sublink subquery */
|
||||||
@ -169,15 +139,12 @@ contain_var_reference(Node *node, int varno, int varattno, int levelsup)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Must be prepared to start with a Query or a bare expression tree;
|
* Must be prepared to start with a Query or a bare expression tree;
|
||||||
* if it's a Query, go straight to query_tree_walker to make sure that
|
* if it's a Query, we don't want to increment sublevels_up.
|
||||||
* sublevels_up doesn't get incremented prematurely.
|
|
||||||
*/
|
*/
|
||||||
if (node && IsA(node, Query))
|
return query_or_expression_tree_walker(node,
|
||||||
return query_tree_walker((Query *) node,
|
contain_var_reference_walker,
|
||||||
contain_var_reference_walker,
|
(void *) &context,
|
||||||
(void *) &context, 0);
|
0);
|
||||||
else
|
|
||||||
return contain_var_reference_walker(node, &context);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
@ -196,24 +163,6 @@ contain_var_reference_walker(Node *node,
|
|||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (is_subplan(node))
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* Already-planned subquery. Examine the args list (parameters to
|
|
||||||
* be passed to subquery), as well as the exprs list which is
|
|
||||||
* executed by the outer query. But short-circuit recursion into
|
|
||||||
* the subquery itself, which would be a waste of effort.
|
|
||||||
*/
|
|
||||||
SubPlan *subplan = (SubPlan *) node;
|
|
||||||
|
|
||||||
if (contain_var_reference_walker((Node *) subplan->exprs,
|
|
||||||
context))
|
|
||||||
return true;
|
|
||||||
if (contain_var_reference_walker((Node *) subplan->args,
|
|
||||||
context))
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (IsA(node, Query))
|
if (IsA(node, Query))
|
||||||
{
|
{
|
||||||
/* Recurse into RTE subquery or not-yet-planned sublink subquery */
|
/* Recurse into RTE subquery or not-yet-planned sublink subquery */
|
||||||
@ -361,32 +310,16 @@ flatten_join_alias_vars_mutator(Node *node,
|
|||||||
return flatten_join_alias_vars_mutator(newvar, context);
|
return flatten_join_alias_vars_mutator(newvar, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Since expression_tree_mutator won't touch subselects, we have to
|
|
||||||
* handle them specially.
|
|
||||||
*/
|
|
||||||
if (IsA(node, SubLink))
|
|
||||||
{
|
|
||||||
SubLink *sublink = (SubLink *) node;
|
|
||||||
SubLink *newnode;
|
|
||||||
|
|
||||||
FLATCOPY(newnode, sublink, SubLink);
|
|
||||||
MUTATE(newnode->lefthand, sublink->lefthand, List *,
|
|
||||||
flatten_join_alias_vars_mutator, context);
|
|
||||||
MUTATE(newnode->subselect, sublink->subselect, Node *,
|
|
||||||
flatten_join_alias_vars_mutator, context);
|
|
||||||
return (Node *) newnode;
|
|
||||||
}
|
|
||||||
if (IsA(node, Query))
|
if (IsA(node, Query))
|
||||||
{
|
{
|
||||||
/* Recurse into RTE subquery or not-yet-planned sublink subquery */
|
/* Recurse into RTE subquery or not-yet-planned sublink subquery */
|
||||||
Query *query = (Query *) node;
|
|
||||||
Query *newnode;
|
Query *newnode;
|
||||||
|
|
||||||
FLATCOPY(newnode, query, Query);
|
|
||||||
context->sublevels_up++;
|
context->sublevels_up++;
|
||||||
query_tree_mutator(newnode, flatten_join_alias_vars_mutator,
|
newnode = query_tree_mutator((Query *) node,
|
||||||
(void *) context, QTW_IGNORE_JOINALIASES);
|
flatten_join_alias_vars_mutator,
|
||||||
|
(void *) context,
|
||||||
|
QTW_IGNORE_JOINALIASES);
|
||||||
context->sublevels_up--;
|
context->sublevels_up--;
|
||||||
return (Node *) newnode;
|
return (Node *) newnode;
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteDefine.c,v 1.81 2002/12/05 04:04:42 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteDefine.c,v 1.82 2003/01/17 02:01:16 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -467,7 +467,7 @@ setRuleCheckAsUser(Query *qry, AclId userid)
|
|||||||
/* ignore subqueries in rtable because we already processed them */
|
/* ignore subqueries in rtable because we already processed them */
|
||||||
if (qry->hasSubLinks)
|
if (qry->hasSubLinks)
|
||||||
query_tree_walker(qry, setRuleCheckAsUser_walker, (void *) &userid,
|
query_tree_walker(qry, setRuleCheckAsUser_walker, (void *) &userid,
|
||||||
QTW_IGNORE_SUBQUERIES);
|
QTW_IGNORE_RT_SUBQUERIES);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.115 2002/12/17 01:18:32 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.116 2003/01/17 02:01:16 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -820,7 +820,7 @@ fireRIRrules(Query *parsetree)
|
|||||||
*/
|
*/
|
||||||
if (parsetree->hasSubLinks)
|
if (parsetree->hasSubLinks)
|
||||||
query_tree_walker(parsetree, fireRIRonSubLink, NULL,
|
query_tree_walker(parsetree, fireRIRonSubLink, NULL,
|
||||||
QTW_IGNORE_SUBQUERIES);
|
QTW_IGNORE_RT_SUBQUERIES);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the query was marked having aggregates, check if this is still
|
* If the query was marked having aggregates, check if this is still
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteManip.c,v 1.68 2002/12/12 15:49:40 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteManip.c,v 1.69 2003/01/17 02:01:16 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -22,15 +22,6 @@
|
|||||||
#include "utils/lsyscache.h"
|
#include "utils/lsyscache.h"
|
||||||
|
|
||||||
|
|
||||||
/* macros borrowed from expression_tree_mutator */
|
|
||||||
|
|
||||||
#define FLATCOPY(newnode, node, nodetype) \
|
|
||||||
( (newnode) = makeNode(nodetype), \
|
|
||||||
memcpy((newnode), (node), sizeof(nodetype)) )
|
|
||||||
|
|
||||||
#define MUTATE(newfield, oldfield, fieldtype, mutator, context) \
|
|
||||||
( (newfield) = (fieldtype) mutator((Node *) (oldfield), (context)) )
|
|
||||||
|
|
||||||
static bool checkExprHasAggs_walker(Node *node, void *context);
|
static bool checkExprHasAggs_walker(Node *node, void *context);
|
||||||
static bool checkExprHasSubLink_walker(Node *node, void *context);
|
static bool checkExprHasSubLink_walker(Node *node, void *context);
|
||||||
|
|
||||||
@ -47,11 +38,10 @@ checkExprHasAggs(Node *node)
|
|||||||
* If a Query is passed, examine it --- but we will not recurse into
|
* If a Query is passed, examine it --- but we will not recurse into
|
||||||
* sub-Queries.
|
* sub-Queries.
|
||||||
*/
|
*/
|
||||||
if (node && IsA(node, Query))
|
return query_or_expression_tree_walker(node,
|
||||||
return query_tree_walker((Query *) node, checkExprHasAggs_walker,
|
checkExprHasAggs_walker,
|
||||||
NULL, QTW_IGNORE_SUBQUERIES);
|
NULL,
|
||||||
else
|
QTW_IGNORE_RT_SUBQUERIES);
|
||||||
return checkExprHasAggs_walker(node, NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
@ -77,11 +67,10 @@ checkExprHasSubLink(Node *node)
|
|||||||
* If a Query is passed, examine it --- but we will not recurse into
|
* If a Query is passed, examine it --- but we will not recurse into
|
||||||
* sub-Queries.
|
* sub-Queries.
|
||||||
*/
|
*/
|
||||||
if (node && IsA(node, Query))
|
return query_or_expression_tree_walker(node,
|
||||||
return query_tree_walker((Query *) node, checkExprHasSubLink_walker,
|
checkExprHasSubLink_walker,
|
||||||
NULL, QTW_IGNORE_SUBQUERIES);
|
NULL,
|
||||||
else
|
QTW_IGNORE_RT_SUBQUERIES);
|
||||||
return checkExprHasSubLink_walker(node, NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
@ -380,14 +369,12 @@ IncrementVarSublevelsUp(Node *node, int delta_sublevels_up,
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Must be prepared to start with a Query or a bare expression tree;
|
* Must be prepared to start with a Query or a bare expression tree;
|
||||||
* if it's a Query, go straight to query_tree_walker to make sure that
|
* if it's a Query, we don't want to increment sublevels_up.
|
||||||
* sublevels_up doesn't get incremented prematurely.
|
|
||||||
*/
|
*/
|
||||||
if (node && IsA(node, Query))
|
query_or_expression_tree_walker(node,
|
||||||
query_tree_walker((Query *) node, IncrementVarSublevelsUp_walker,
|
IncrementVarSublevelsUp_walker,
|
||||||
(void *) &context, 0);
|
(void *) &context,
|
||||||
else
|
0);
|
||||||
IncrementVarSublevelsUp_walker(node, &context);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -461,14 +448,12 @@ rangeTableEntry_used(Node *node, int rt_index, int sublevels_up)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Must be prepared to start with a Query or a bare expression tree;
|
* Must be prepared to start with a Query or a bare expression tree;
|
||||||
* if it's a Query, go straight to query_tree_walker to make sure that
|
* if it's a Query, we don't want to increment sublevels_up.
|
||||||
* sublevels_up doesn't get incremented prematurely.
|
|
||||||
*/
|
*/
|
||||||
if (node && IsA(node, Query))
|
return query_or_expression_tree_walker(node,
|
||||||
return query_tree_walker((Query *) node, rangeTableEntry_used_walker,
|
rangeTableEntry_used_walker,
|
||||||
(void *) &context, 0);
|
(void *) &context,
|
||||||
else
|
0);
|
||||||
return rangeTableEntry_used_walker(node, &context);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -527,14 +512,12 @@ attribute_used(Node *node, int rt_index, int attno, int sublevels_up)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Must be prepared to start with a Query or a bare expression tree;
|
* Must be prepared to start with a Query or a bare expression tree;
|
||||||
* if it's a Query, go straight to query_tree_walker to make sure that
|
* if it's a Query, we don't want to increment sublevels_up.
|
||||||
* sublevels_up doesn't get incremented prematurely.
|
|
||||||
*/
|
*/
|
||||||
if (node && IsA(node, Query))
|
return query_or_expression_tree_walker(node,
|
||||||
return query_tree_walker((Query *) node, attribute_used_walker,
|
attribute_used_walker,
|
||||||
(void *) &context, 0);
|
(void *) &context,
|
||||||
else
|
0);
|
||||||
return attribute_used_walker(node, &context);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -820,30 +803,16 @@ ResolveNew_mutator(Node *node, ResolveNew_context *context)
|
|||||||
/* otherwise fall through to copy the var normally */
|
/* otherwise fall through to copy the var normally */
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Since expression_tree_mutator won't touch subselects, we have to
|
|
||||||
* handle them specially.
|
|
||||||
*/
|
|
||||||
if (IsA(node, SubLink))
|
|
||||||
{
|
|
||||||
SubLink *sublink = (SubLink *) node;
|
|
||||||
SubLink *newnode;
|
|
||||||
|
|
||||||
FLATCOPY(newnode, sublink, SubLink);
|
|
||||||
MUTATE(newnode->lefthand, sublink->lefthand, List *,
|
|
||||||
ResolveNew_mutator, context);
|
|
||||||
MUTATE(newnode->subselect, sublink->subselect, Node *,
|
|
||||||
ResolveNew_mutator, context);
|
|
||||||
return (Node *) newnode;
|
|
||||||
}
|
|
||||||
if (IsA(node, Query))
|
if (IsA(node, Query))
|
||||||
{
|
{
|
||||||
Query *query = (Query *) node;
|
/* Recurse into RTE subquery or not-yet-planned sublink subquery */
|
||||||
Query *newnode;
|
Query *newnode;
|
||||||
|
|
||||||
FLATCOPY(newnode, query, Query);
|
|
||||||
context->sublevels_up++;
|
context->sublevels_up++;
|
||||||
query_tree_mutator(newnode, ResolveNew_mutator, context, 0);
|
newnode = query_tree_mutator((Query *) node,
|
||||||
|
ResolveNew_mutator,
|
||||||
|
(void *) context,
|
||||||
|
0);
|
||||||
context->sublevels_up--;
|
context->sublevels_up--;
|
||||||
return (Node *) newnode;
|
return (Node *) newnode;
|
||||||
}
|
}
|
||||||
@ -865,21 +834,12 @@ ResolveNew(Node *node, int target_varno, int sublevels_up,
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Must be prepared to start with a Query or a bare expression tree;
|
* Must be prepared to start with a Query or a bare expression tree;
|
||||||
* if it's a Query, go straight to query_tree_mutator to make sure
|
* if it's a Query, we don't want to increment sublevels_up.
|
||||||
* that sublevels_up doesn't get incremented prematurely.
|
|
||||||
*/
|
*/
|
||||||
if (node && IsA(node, Query))
|
return query_or_expression_tree_mutator(node,
|
||||||
{
|
ResolveNew_mutator,
|
||||||
Query *query = (Query *) node;
|
(void *) &context,
|
||||||
Query *newnode;
|
0);
|
||||||
|
|
||||||
FLATCOPY(newnode, query, Query);
|
|
||||||
query_tree_mutator(newnode, ResolveNew_mutator,
|
|
||||||
(void *) &context, 0);
|
|
||||||
return (Node *) newnode;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return ResolveNew_mutator(node, &context);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -959,31 +919,16 @@ HandleRIRAttributeRule_mutator(Node *node,
|
|||||||
/* otherwise fall through to copy the var normally */
|
/* otherwise fall through to copy the var normally */
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Since expression_tree_mutator won't touch subselects, we have to
|
|
||||||
* handle them specially.
|
|
||||||
*/
|
|
||||||
if (IsA(node, SubLink))
|
|
||||||
{
|
|
||||||
SubLink *sublink = (SubLink *) node;
|
|
||||||
SubLink *newnode;
|
|
||||||
|
|
||||||
FLATCOPY(newnode, sublink, SubLink);
|
|
||||||
MUTATE(newnode->lefthand, sublink->lefthand, List *,
|
|
||||||
HandleRIRAttributeRule_mutator, context);
|
|
||||||
MUTATE(newnode->subselect, sublink->subselect, Node *,
|
|
||||||
HandleRIRAttributeRule_mutator, context);
|
|
||||||
return (Node *) newnode;
|
|
||||||
}
|
|
||||||
if (IsA(node, Query))
|
if (IsA(node, Query))
|
||||||
{
|
{
|
||||||
Query *query = (Query *) node;
|
/* Recurse into RTE subquery or not-yet-planned sublink subquery */
|
||||||
Query *newnode;
|
Query *newnode;
|
||||||
|
|
||||||
FLATCOPY(newnode, query, Query);
|
|
||||||
context->sublevels_up++;
|
context->sublevels_up++;
|
||||||
query_tree_mutator(newnode, HandleRIRAttributeRule_mutator,
|
newnode = query_tree_mutator((Query *) node,
|
||||||
context, 0);
|
HandleRIRAttributeRule_mutator,
|
||||||
|
(void *) context,
|
||||||
|
0);
|
||||||
context->sublevels_up--;
|
context->sublevels_up--;
|
||||||
return (Node *) newnode;
|
return (Node *) newnode;
|
||||||
}
|
}
|
||||||
@ -1010,8 +955,10 @@ HandleRIRAttributeRule(Query *parsetree,
|
|||||||
context.badsql = badsql;
|
context.badsql = badsql;
|
||||||
context.sublevels_up = 0;
|
context.sublevels_up = 0;
|
||||||
|
|
||||||
query_tree_mutator(parsetree, HandleRIRAttributeRule_mutator,
|
query_tree_mutator(parsetree,
|
||||||
(void *) &context, 0);
|
HandleRIRAttributeRule_mutator,
|
||||||
|
(void *) &context,
|
||||||
|
QTW_DONT_COPY_QUERY);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* NOT_USED */
|
#endif /* NOT_USED */
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $Id: clauses.h,v 1.59 2003/01/15 19:35:47 tgl Exp $
|
* $Id: clauses.h,v 1.60 2003/01/17 02:01:21 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -75,12 +75,18 @@ extern Node *expression_tree_mutator(Node *node, Node *(*mutator) (),
|
|||||||
void *context);
|
void *context);
|
||||||
|
|
||||||
/* flags bits for query_tree_walker and query_tree_mutator */
|
/* flags bits for query_tree_walker and query_tree_mutator */
|
||||||
#define QTW_IGNORE_SUBQUERIES 0x01 /* subqueries in rtable */
|
#define QTW_IGNORE_RT_SUBQUERIES 0x01 /* subqueries in rtable */
|
||||||
#define QTW_IGNORE_JOINALIASES 0x02 /* JOIN alias var lists */
|
#define QTW_IGNORE_JOINALIASES 0x02 /* JOIN alias var lists */
|
||||||
|
#define QTW_DONT_COPY_QUERY 0x04 /* do not copy top Query */
|
||||||
|
|
||||||
extern bool query_tree_walker(Query *query, bool (*walker) (),
|
extern bool query_tree_walker(Query *query, bool (*walker) (),
|
||||||
void *context, int flags);
|
void *context, int flags);
|
||||||
extern void query_tree_mutator(Query *query, Node *(*mutator) (),
|
extern Query *query_tree_mutator(Query *query, Node *(*mutator) (),
|
||||||
void *context, int flags);
|
void *context, int flags);
|
||||||
|
|
||||||
|
extern bool query_or_expression_tree_walker(Node *node, bool (*walker) (),
|
||||||
|
void *context, int flags);
|
||||||
|
extern Node *query_or_expression_tree_mutator(Node *node, Node *(*mutator) (),
|
||||||
|
void *context, int flags);
|
||||||
|
|
||||||
#endif /* CLAUSES_H */
|
#endif /* CLAUSES_H */
|
||||||
|
Reference in New Issue
Block a user