From ecef2caae9aefdd88b086871ba50bb70c2c8c5e8 Mon Sep 17 00:00:00 2001 From: Tom Lane <tgl@sss.pgh.pa.us> Date: Mon, 9 Aug 1999 00:56:05 +0000 Subject: [PATCH] Clean up routines in setrefs.c by replacing individual tree walking logic with expression_tree_walker/mutator calls. --- src/backend/optimizer/plan/setrefs.c | 702 ++++++--------------------- src/include/optimizer/planmain.h | 6 +- 2 files changed, 157 insertions(+), 551 deletions(-) diff --git a/src/backend/optimizer/plan/setrefs.c b/src/backend/optimizer/plan/setrefs.c index 641241a7fd2..c4c19780ca9 100644 --- a/src/backend/optimizer/plan/setrefs.c +++ b/src/backend/optimizer/plan/setrefs.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/setrefs.c,v 1.53 1999/07/16 04:59:20 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/setrefs.c,v 1.54 1999/08/09 00:56:05 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -15,8 +15,6 @@ #include "postgres.h" - - #include "nodes/makefuncs.h" #include "nodes/nodeFuncs.h" #include "optimizer/clauses.h" @@ -24,22 +22,40 @@ #include "optimizer/tlist.h" #include "optimizer/var.h" +typedef struct { + List *outer_tlist; + List *inner_tlist; +} replace_joinvar_refs_context; + +typedef struct { + Index subvarno; + List *subplanTargetList; +} replace_vars_with_subplan_refs_context; + +typedef struct { + List *groupClause; + List *targetList; +} check_having_for_ungrouped_vars_context; + static void set_join_tlist_references(Join *join); static void set_nonamescan_tlist_references(SeqScan *nonamescan); static void set_noname_tlist_references(Noname *noname); -static Node *replace_clause_joinvar_refs(Node *clause, - List *outer_tlist, - List *inner_tlist); -static Var *replace_joinvar_refs(Var *var, - List *outer_tlist, - List *inner_tlist); +static Node *replace_joinvar_refs(Node *clause, + List *outer_tlist, + List *inner_tlist); +static Node *replace_joinvar_refs_mutator(Node *node, + replace_joinvar_refs_context *context); static List *tlist_noname_references(Oid nonameid, List *tlist); -static bool OperandIsInner(Node *opnd, int inner_relid); -static List *pull_agg_clause(Node *clause); static void set_result_tlist_references(Result *resultNode); static void replace_vars_with_subplan_refs(Node *clause, - Index subvarno, - List *subplanTargetList); + Index subvarno, + List *subplanTargetList); +static bool replace_vars_with_subplan_refs_walker(Node *node, + replace_vars_with_subplan_refs_context *context); +static List *pull_agg_clause(Node *clause); +static bool pull_agg_clause_walker(Node *node, List **listptr); +static bool check_having_for_ungrouped_vars_walker(Node *node, + check_having_for_ungrouped_vars_context *context); /***************************************************************************** * @@ -107,12 +123,12 @@ set_join_tlist_references(Join *join) foreach(entry, qptlist) { TargetEntry *xtl = (TargetEntry *) lfirst(entry); - Node *joinvar = replace_clause_joinvar_refs(xtl->expr, - outer_tlist, - inner_tlist); + Node *joinexpr = replace_joinvar_refs(xtl->expr, + outer_tlist, + inner_tlist); new_join_targetlist = lappend(new_join_targetlist, - makeTargetEntry(xtl->resdom, joinvar)); + makeTargetEntry(xtl->resdom, joinexpr)); } ((Plan *) join)->targetlist = new_join_targetlist; @@ -173,7 +189,7 @@ set_noname_tlist_references(Noname *noname) * Creates a new set of join clauses by changing the varno/varattno * values of variables in the clauses to reference target list values * from the outer and inner join relation target lists. - * This is just an external interface for replace_clause_joinvar_refs. + * This is just an external interface for replace_joinvar_refs. * * 'clauses' is the list of join clauses * 'outer_tlist' is the target list of the outer join relation @@ -188,291 +204,75 @@ join_references(List *clauses, List *outer_tlist, List *inner_tlist) { - return (List *) replace_clause_joinvar_refs((Node *) clauses, - outer_tlist, - inner_tlist); + return (List *) replace_joinvar_refs((Node *) clauses, + outer_tlist, + inner_tlist); } /* - * index_outerjoin_references - * Given a list of join clauses, replace the operand corresponding to the - * outer relation in the join with references to the corresponding target - * list element in 'outer_tlist' (the outer is rather obscurely - * identified as the side that doesn't contain a var whose varno equals - * 'inner_relid'). - * - * As a side effect, the operator is replaced by the regproc id. - * - * 'inner_indxqual' is the list of join clauses (so-called because they - * are used as qualifications for the inner (inbex) scan of a nestloop) - * - * Returns the new list of clauses. - * - */ -List * -index_outerjoin_references(List *inner_indxqual, - List *outer_tlist, - Index inner_relid) -{ - List *t_list = NIL; - Expr *temp = NULL; - List *t_clause = NIL; - Expr *clause = NULL; - - foreach(t_clause, inner_indxqual) - { - clause = lfirst(t_clause); - - /* - * if inner scan on the right. - */ - if (OperandIsInner((Node *) get_rightop(clause), inner_relid)) - { - Var *joinvar = (Var *) - replace_clause_joinvar_refs((Node *) get_leftop(clause), - outer_tlist, - NIL); - - temp = make_opclause(replace_opid((Oper *) ((Expr *) clause)->oper), - joinvar, - get_rightop(clause)); - t_list = lappend(t_list, temp); - } - else - { - /* inner scan on left */ - Var *joinvar = (Var *) - replace_clause_joinvar_refs((Node *) get_rightop(clause), - outer_tlist, - NIL); - - temp = make_opclause(replace_opid((Oper *) ((Expr *) clause)->oper), - get_leftop(clause), - joinvar); - t_list = lappend(t_list, temp); - } - - } - return t_list; -} - -/* - * replace_clause_joinvar_refs * replace_joinvar_refs * * Replaces all variables within a join clause with a new var node * whose varno/varattno fields contain a reference to a target list * element from either the outer or inner join relation. * + * Returns a suitably modified copy of the join clause; + * the original is not modified (and must not be!) + * + * Side effect: also runs fix_opids on the modified join clause. + * Really ought to make that happen in a uniform, consistent place... + * * 'clause' is the join clause * 'outer_tlist' is the target list of the outer join relation * 'inner_tlist' is the target list of the inner join relation - * - * Returns the new join clause. - * NB: it is critical that the original clause structure not be modified! - * The changes must be applied to a copy. - * - * XXX the current implementation does not copy unchanged primitive - * nodes; they remain shared with the original. Is this safe? */ static Node * -replace_clause_joinvar_refs(Node *clause, - List *outer_tlist, - List *inner_tlist) +replace_joinvar_refs(Node *clause, + List *outer_tlist, + List *inner_tlist) { - if (clause == NULL) - return NULL; - if (IsA(clause, Var)) - { - Var *temp = replace_joinvar_refs((Var *) clause, - outer_tlist, inner_tlist); + replace_joinvar_refs_context context; - if (temp != NULL) - return (Node *) temp; - else - return clause; - } - else if (single_node(clause)) - return clause; - else if (and_clause(clause)) - { - return (Node *) make_andclause((List *) - replace_clause_joinvar_refs((Node *) ((Expr *) clause)->args, - outer_tlist, - inner_tlist)); - } - else if (or_clause(clause)) - { - return (Node *) make_orclause((List *) - replace_clause_joinvar_refs((Node *) ((Expr *) clause)->args, - outer_tlist, - inner_tlist)); - } - else if (IsA(clause, ArrayRef)) - { - ArrayRef *oldnode = (ArrayRef *) clause; - ArrayRef *newnode = makeNode(ArrayRef); - - newnode->refattrlength = oldnode->refattrlength; - newnode->refelemlength = oldnode->refelemlength; - newnode->refelemtype = oldnode->refelemtype; - newnode->refelembyval = oldnode->refelembyval; - newnode->refupperindexpr = (List *) - replace_clause_joinvar_refs((Node *) oldnode->refupperindexpr, - outer_tlist, - inner_tlist); - newnode->reflowerindexpr = (List *) - replace_clause_joinvar_refs((Node *) oldnode->reflowerindexpr, - outer_tlist, - inner_tlist); - newnode->refexpr = - replace_clause_joinvar_refs(oldnode->refexpr, - outer_tlist, - inner_tlist); - newnode->refassgnexpr = - replace_clause_joinvar_refs(oldnode->refassgnexpr, - outer_tlist, - inner_tlist); - - return (Node *) newnode; - } - else if (is_funcclause(clause)) - { - return (Node *) make_funcclause( - (Func *) ((Expr *) clause)->oper, - (List *) replace_clause_joinvar_refs( - (Node *) ((Expr *) clause)->args, - outer_tlist, - inner_tlist)); - } - else if (not_clause(clause)) - { - return (Node *) make_notclause((Expr *) - replace_clause_joinvar_refs( - (Node *) get_notclausearg((Expr *) clause), - outer_tlist, - inner_tlist)); - } - else if (is_opclause(clause)) - { - return (Node *) make_opclause( - replace_opid((Oper *) ((Expr *) clause)->oper), - (Var *) replace_clause_joinvar_refs( - (Node *) get_leftop((Expr *) clause), - outer_tlist, - inner_tlist), - (Var *) replace_clause_joinvar_refs( - (Node *) get_rightop((Expr *) clause), - outer_tlist, - inner_tlist)); - } - else if (IsA(clause, List)) - { - List *t_list = NIL; - List *subclause; - - foreach(subclause, (List *) clause) - { - t_list = lappend(t_list, - replace_clause_joinvar_refs(lfirst(subclause), - outer_tlist, - inner_tlist)); - } - return (Node *) t_list; - } - else if (is_subplan(clause)) - { - /* This is a tad wasteful of space, but it works... */ - Expr *newclause = (Expr *) copyObject(clause); - - newclause->args = (List *) - replace_clause_joinvar_refs((Node *) newclause->args, - outer_tlist, - inner_tlist); - ((SubPlan *) newclause->oper)->sublink->oper = (List *) - replace_clause_joinvar_refs( - (Node *) ((SubPlan *) newclause->oper)->sublink->oper, - outer_tlist, - inner_tlist); - return (Node *) newclause; - } - else if (IsA(clause, CaseExpr)) - { - CaseExpr *oldnode = (CaseExpr *) clause; - CaseExpr *newnode = makeNode(CaseExpr); - - newnode->casetype = oldnode->casetype; - newnode->arg = oldnode->arg; /* XXX should always be null - * anyway ... */ - newnode->args = (List *) - replace_clause_joinvar_refs((Node *) oldnode->args, - outer_tlist, - inner_tlist); - newnode->defresult = - replace_clause_joinvar_refs(oldnode->defresult, - outer_tlist, - inner_tlist); - - return (Node *) newnode; - } - else if (IsA(clause, CaseWhen)) - { - CaseWhen *oldnode = (CaseWhen *) clause; - CaseWhen *newnode = makeNode(CaseWhen); - - newnode->expr = - replace_clause_joinvar_refs(oldnode->expr, - outer_tlist, - inner_tlist); - newnode->result = - replace_clause_joinvar_refs(oldnode->result, - outer_tlist, - inner_tlist); - - return (Node *) newnode; - } - else - { - elog(ERROR, "replace_clause_joinvar_refs: unsupported clause %d", - nodeTag(clause)); - return NULL; - } + context.outer_tlist = outer_tlist; + context.inner_tlist = inner_tlist; + return (Node *) fix_opids((List *) + replace_joinvar_refs_mutator(clause, &context)); } -static Var * -replace_joinvar_refs(Var *var, List *outer_tlist, List *inner_tlist) +static Node * +replace_joinvar_refs_mutator(Node *node, + replace_joinvar_refs_context *context) { - Resdom *outer_resdom; - - outer_resdom = tlist_member(var, outer_tlist); - - if (outer_resdom != NULL && IsA(outer_resdom, Resdom)) - { - return (makeVar(OUTER, - outer_resdom->resno, - var->vartype, - var->vartypmod, - 0, - var->varnoold, - var->varoattno)); - } - else - { - Resdom *inner_resdom; - - inner_resdom = tlist_member(var, inner_tlist); - if (inner_resdom != NULL && IsA(inner_resdom, Resdom)) - { - return (makeVar(INNER, - inner_resdom->resno, - var->vartype, - var->vartypmod, - 0, - var->varnoold, - var->varoattno)); - } - } - return (Var *) NULL; + if (node == NULL) + return NULL; + if (IsA(node, Var)) + { + Var *var = (Var *) node; + Resdom *resdom = tlist_member(var, context->outer_tlist); + + if (resdom != NULL && IsA(resdom, Resdom)) + return (Node *) makeVar(OUTER, + resdom->resno, + var->vartype, + var->vartypmod, + 0, + var->varnoold, + var->varoattno); + resdom = tlist_member(var, context->inner_tlist); + if (resdom != NULL && IsA(resdom, Resdom)) + return (Node *) makeVar(INNER, + resdom->resno, + var->vartype, + var->vartypmod, + 0, + var->varnoold, + var->varoattno); + /* Var not in either tlist, return an unmodified copy. */ + return copyObject(node); + } + return expression_tree_mutator(node, + replace_joinvar_refs_mutator, + (void *) context); } /* @@ -494,15 +294,14 @@ tlist_noname_references(Oid nonameid, List *tlist) { List *t_list = NIL; - TargetEntry *noname = (TargetEntry *) NULL; - TargetEntry *xtl = NULL; List *entry; foreach(entry, tlist) { + TargetEntry *xtl = lfirst(entry); AttrNumber oattno; + TargetEntry *noname; - xtl = lfirst(entry); if (IsA(get_expr(xtl), Var)) oattno = ((Var *) xtl->expr)->varoattno; else @@ -531,7 +330,7 @@ tlist_noname_references(Oid nonameid, * * NOTE: * 1) we ignore the right tree! (in the current implementation - * it is always nil + * it is always nil) * 2) this routine will probably *NOT* work with nested dot * fields.... */ @@ -601,131 +400,52 @@ replace_vars_with_subplan_refs(Node *clause, Index subvarno, List *subplanTargetList) { - List *t; + replace_vars_with_subplan_refs_context context; - if (clause == NULL) - return; - if (IsA(clause, Var)) - { + context.subvarno = subvarno; + context.subplanTargetList = subplanTargetList; + replace_vars_with_subplan_refs_walker(clause, &context); +} +static bool +replace_vars_with_subplan_refs_walker(Node *node, + replace_vars_with_subplan_refs_context *context) +{ + if (node == NULL) + return false; + if (IsA(node, Var)) + { /* - * Ha! A Var node! - * * It could be that this varnode has been created by make_groupplan * and is already set up to reference the subplan target list. We * recognize that case by varno = 1, varnoold = -1, varattno = * varoattno, and varlevelsup = 0. (Probably ought to have an * explicit flag, but this should do for now.) */ - Var *var = (Var *) clause; + Var *var = (Var *) node; TargetEntry *subplanVar; if (var->varno == (Index) 1 && var->varnoold == ((Index) -1) && var->varattno == var->varoattno && var->varlevelsup == 0) - return; /* OK to leave it alone */ + return false; /* OK to leave it alone */ /* Otherwise it had better be in the subplan list. */ - subplanVar = match_varid(var, subplanTargetList); + subplanVar = match_varid(var, context->subplanTargetList); if (!subplanVar) elog(ERROR, "replace_vars_with_subplan_refs: variable not in target list"); /* * Change the varno & varattno fields of the var node. */ - var->varno = subvarno; + var->varno = context->subvarno; var->varattno = subplanVar->resdom->resno; + return false; } - else if (single_node(clause)) - { - /* do nothing! */ - } - else if (IsA(clause, Iter)) - replace_vars_with_subplan_refs(((Iter *) clause)->iterexpr, - subvarno, subplanTargetList); - else if (is_subplan(clause)) - { - foreach(t, ((Expr *) clause)->args) - replace_vars_with_subplan_refs(lfirst(t), - subvarno, subplanTargetList); - foreach(t, ((SubPlan *) ((Expr *) clause)->oper)->sublink->oper) - replace_vars_with_subplan_refs(lfirst(((Expr *) lfirst(t))->args), - subvarno, subplanTargetList); - } - else if (IsA(clause, Expr)) - { - - /* - * Recursively scan the arguments of an expression. NOTE: this - * must come after is_subplan() case since subplan is a kind of - * Expr node. - */ - foreach(t, ((Expr *) clause)->args) - replace_vars_with_subplan_refs(lfirst(t), - subvarno, subplanTargetList); - } - else if (IsA(clause, Aggref)) - replace_vars_with_subplan_refs(((Aggref *) clause)->target, - subvarno, subplanTargetList); - else if (IsA(clause, ArrayRef)) - { - ArrayRef *aref = (ArrayRef *) clause; - - foreach(t, aref->refupperindexpr) - replace_vars_with_subplan_refs(lfirst(t), - subvarno, subplanTargetList); - foreach(t, aref->reflowerindexpr) - replace_vars_with_subplan_refs(lfirst(t), - subvarno, subplanTargetList); - replace_vars_with_subplan_refs(aref->refexpr, - subvarno, subplanTargetList); - replace_vars_with_subplan_refs(aref->refassgnexpr, - subvarno, subplanTargetList); - } - else if (case_clause(clause)) - { - foreach(t, ((CaseExpr *) clause)->args) - { - CaseWhen *when = (CaseWhen *) lfirst(t); - - replace_vars_with_subplan_refs(when->expr, - subvarno, subplanTargetList); - replace_vars_with_subplan_refs(when->result, - subvarno, subplanTargetList); - } - replace_vars_with_subplan_refs(((CaseExpr *) clause)->defresult, - subvarno, subplanTargetList); - } - else - { - elog(ERROR, "replace_vars_with_subplan_refs: Cannot handle node type %d", - nodeTag(clause)); - } -} - -static bool -OperandIsInner(Node *opnd, int inner_relid) -{ - - /* - * Can be the inner scan if its a varnode or a function and the - * inner_relid is equal to the varnode's var number or in the case of - * a function the first argument's var number (all args in a - * functional index are from the same relation). - */ - if (IsA(opnd, Var) && - (inner_relid == ((Var *) opnd)->varno)) - return true; - if (is_funcclause(opnd)) - { - List *firstArg = lfirst(((Expr *) opnd)->args); - - if (IsA(firstArg, Var) && - (inner_relid == ((Var *) firstArg)->varno)) - return true; - } - return false; + return expression_tree_walker(node, + replace_vars_with_subplan_refs_walker, + (void *) context); } /***************************************************************************** @@ -787,83 +507,35 @@ set_agg_tlist_references(Agg *aggNode) } /* - * Make a list of all Aggref nodes contained in the given expression. + * pull_agg_clause + * Recursively pulls all Aggref nodes from an expression clause. + * + * Returns list of Aggref nodes found. Note the nodes themselves are not + * copied, only referenced. */ static List * pull_agg_clause(Node *clause) { - List *agg_list = NIL; - List *t; - - if (clause == NULL) - return NIL; - else if (single_node(clause)) - return NIL; - else if (IsA(clause, Iter)) - return pull_agg_clause(((Iter *) clause)->iterexpr); - else if (is_subplan(clause)) - { - SubLink *sublink = ((SubPlan *) ((Expr *) clause)->oper)->sublink; + List *result = NIL; - /* - * Only the lefthand side of the sublink should be checked for - * aggregates to be attached to the aggs list - */ - foreach(t, sublink->lefthand) - agg_list = nconc(pull_agg_clause(lfirst(t)), agg_list); - /* The first argument of ...->oper has also to be checked */ - foreach(t, sublink->oper) - agg_list = nconc(pull_agg_clause(lfirst(t)), agg_list); - } - else if (IsA(clause, Expr)) - { - - /* - * Recursively scan the arguments of an expression. NOTE: this - * must come after is_subplan() case since subplan is a kind of - * Expr node. - */ - foreach(t, ((Expr *) clause)->args) - agg_list = nconc(pull_agg_clause(lfirst(t)), agg_list); - } - else if (IsA(clause, Aggref)) - { - return lcons(clause, - pull_agg_clause(((Aggref *) clause)->target)); - } - else if (IsA(clause, ArrayRef)) - { - ArrayRef *aref = (ArrayRef *) clause; - - foreach(t, aref->refupperindexpr) - agg_list = nconc(pull_agg_clause(lfirst(t)), agg_list); - foreach(t, aref->reflowerindexpr) - agg_list = nconc(pull_agg_clause(lfirst(t)), agg_list); - agg_list = nconc(pull_agg_clause(aref->refexpr), agg_list); - agg_list = nconc(pull_agg_clause(aref->refassgnexpr), agg_list); - } - else if (case_clause(clause)) - { - foreach(t, ((CaseExpr *) clause)->args) - { - CaseWhen *when = (CaseWhen *) lfirst(t); + pull_agg_clause_walker(clause, &result); + return result; +} - agg_list = nconc(agg_list, pull_agg_clause(when->expr)); - agg_list = nconc(agg_list, pull_agg_clause(when->result)); - } - agg_list = nconc(pull_agg_clause(((CaseExpr *) clause)->defresult), - agg_list); - } - else +static bool +pull_agg_clause_walker(Node *node, List **listptr) +{ + if (node == NULL) + return false; + if (IsA(node, Aggref)) { - elog(ERROR, "pull_agg_clause: Cannot handle node type %d", - nodeTag(clause)); + *listptr = lappend(*listptr, node); + return false; } - - return agg_list; + return expression_tree_walker(node, pull_agg_clause_walker, + (void *) listptr); } - /* * check_having_for_ungrouped_vars takes the havingQual and the list of * GROUP BY clauses and checks for subplans in the havingQual that are being @@ -882,45 +554,43 @@ void check_having_for_ungrouped_vars(Node *clause, List *groupClause, List *targetList) { - List *t; - - if (clause == NULL) - return; + check_having_for_ungrouped_vars_context context; - if (IsA(clause, Var)) - { + context.groupClause = groupClause; + context.targetList = targetList; + check_having_for_ungrouped_vars_walker(clause, &context); +} - /* - * Ignore vars elsewhere in the having clause, since the parser - * already checked 'em. - */ - } - else if (single_node(clause)) - { - /* ignore */ - } - else if (IsA(clause, Iter)) - { - check_having_for_ungrouped_vars(((Iter *) clause)->iterexpr, - groupClause, targetList); - } - else if (is_subplan(clause)) +static bool +check_having_for_ungrouped_vars_walker(Node *node, + check_having_for_ungrouped_vars_context *context) +{ + if (node == NULL) + return false; + /* + * We can ignore Vars other than in subplan args lists, + * since the parser already checked 'em. + */ + if (is_subplan(node)) { - /* * The args list of the subplan node represents attributes from * outside passed into the sublink. */ - foreach(t, ((Expr *) clause)->args) + List *t; + + foreach(t, ((Expr *) node)->args) { + Node *thisarg = lfirst(t); bool contained_in_group_clause = false; List *gl; - foreach(gl, groupClause) + foreach(gl, context->groupClause) { - if (var_equal(lfirst(t), - get_groupclause_expr((GroupClause *) - lfirst(gl), targetList))) + Var *groupexpr = get_groupclause_expr(lfirst(gl), + context->targetList); + + if (var_equal((Var *) thisarg, groupexpr)) { contained_in_group_clause = true; break; @@ -931,69 +601,7 @@ check_having_for_ungrouped_vars(Node *clause, List *groupClause, elog(ERROR, "Sub-SELECT in HAVING clause must use only GROUPed attributes from outer SELECT"); } } - else if (IsA(clause, Expr)) - { - - /* - * Recursively scan the arguments of an expression. NOTE: this - * must come after is_subplan() case since subplan is a kind of - * Expr node. - */ - foreach(t, ((Expr *) clause)->args) - check_having_for_ungrouped_vars(lfirst(t), groupClause, - targetList); - } - else if (IsA(clause, List)) - { - - /* - * Recursively scan AND subclauses (see NOTE above). - */ - foreach(t, ((List *) clause)) - check_having_for_ungrouped_vars(lfirst(t), groupClause, - targetList); - } - else if (IsA(clause, Aggref)) - { - check_having_for_ungrouped_vars(((Aggref *) clause)->target, - groupClause, targetList); - } - else if (IsA(clause, ArrayRef)) - { - ArrayRef *aref = (ArrayRef *) clause; - - /* - * This is an arrayref. Recursively call this routine for its - * expression and its index expression... - */ - foreach(t, aref->refupperindexpr) - check_having_for_ungrouped_vars(lfirst(t), groupClause, - targetList); - foreach(t, aref->reflowerindexpr) - check_having_for_ungrouped_vars(lfirst(t), groupClause, - targetList); - check_having_for_ungrouped_vars(aref->refexpr, groupClause, - targetList); - check_having_for_ungrouped_vars(aref->refassgnexpr, groupClause, - targetList); - } - else if (case_clause(clause)) - { - foreach(t, ((CaseExpr *) clause)->args) - { - CaseWhen *when = (CaseWhen *) lfirst(t); - - check_having_for_ungrouped_vars(when->expr, groupClause, - targetList); - check_having_for_ungrouped_vars(when->result, groupClause, - targetList); - } - check_having_for_ungrouped_vars(((CaseExpr *) clause)->defresult, - groupClause, targetList); - } - else - { - elog(ERROR, "check_having_for_ungrouped_vars: Cannot handle node type %d", - nodeTag(clause)); - } + return expression_tree_walker(node, + check_having_for_ungrouped_vars_walker, + (void *) context); } diff --git a/src/include/optimizer/planmain.h b/src/include/optimizer/planmain.h index 9e376174466..0ba017471d1 100644 --- a/src/include/optimizer/planmain.h +++ b/src/include/optimizer/planmain.h @@ -6,7 +6,7 @@ * * Copyright (c) 1994, Regents of the University of California * - * $Id: planmain.h,v 1.29 1999/07/15 15:21:22 momjian Exp $ + * $Id: planmain.h,v 1.30 1999/08/09 00:56:04 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -49,9 +49,7 @@ extern void add_missing_vars_to_tlist(Query *root, List *tlist); */ extern void set_tlist_references(Plan *plan); extern List *join_references(List *clauses, List *outer_tlist, - List *inner_tlist); -extern List *index_outerjoin_references(List *inner_indxqual, - List *outer_tlist, Index inner_relid); + List *inner_tlist); extern void replace_tlist_with_subplan_refs(List *tlist, Index subvarno, List *subplanTargetList); -- GitLab