diff --git a/src/backend/catalog/dependency.c b/src/backend/catalog/dependency.c index 8fb977e725..53ad37bd61 100644 --- a/src/backend/catalog/dependency.c +++ b/src/backend/catalog/dependency.c @@ -8,7 +8,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/catalog/dependency.c,v 1.9 2002/09/04 20:31:13 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/catalog/dependency.c,v 1.10 2002/09/11 14:48:54 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -684,6 +684,12 @@ recordDependencyOnExpr(const ObjectAddress *depender, /* * Recursively search an expression tree for object references. + * + * Note: we avoid creating references to columns of tables that participate + * in an SQL JOIN construct, but are not actually used anywhere in the query. + * To do so, we do not scan the joinaliasvars list of a join RTE while + * scanning the query rangetable, but instead scan each individual entry + * of the alias list when we find a reference to it. */ static bool find_expr_references_walker(Node *node, @@ -716,10 +722,24 @@ find_expr_references_walker(Node *node, elog(ERROR, "find_expr_references_walker: bogus varno %d", var->varno); rte = rt_fetch(var->varno, rtable); - /* If it's a plain relation, reference this column */ if (rte->rtekind == RTE_RELATION) + { + /* If it's a plain relation, reference this column */ + /* NB: this code works for whole-row Var with attno 0, too */ add_object_address(OCLASS_CLASS, rte->relid, var->varattno, &context->addrs); + } + else if (rte->rtekind == RTE_JOIN) + { + /* Scan join output column to add references to join inputs */ + if (var->varattno <= 0 || + var->varattno > length(rte->joinaliasvars)) + elog(ERROR, "find_expr_references_walker: bogus varattno %d", + var->varattno); + find_expr_references_walker((Node *) nth(var->varattno - 1, + rte->joinaliasvars), + context); + } return false; } if (IsA(node, Expr)) @@ -766,7 +786,7 @@ find_expr_references_walker(Node *node, * Add whole-relation refs for each plain relation mentioned in * the subquery's rtable. (Note: query_tree_walker takes care of * recursing into RTE_FUNCTION and RTE_SUBQUERY RTEs, so no need - * to do that here.) + * to do that here. But keep it from looking at join alias lists.) */ foreach(rtable, query->rtable) { @@ -781,7 +801,8 @@ find_expr_references_walker(Node *node, context->rtables = lcons(query->rtable, context->rtables); result = query_tree_walker(query, find_expr_references_walker, - (void *) context, true); + (void *) context, + QTW_IGNORE_JOINALIASES); context->rtables = lnext(context->rtables); return result; } diff --git a/src/backend/optimizer/prep/prepunion.c b/src/backend/optimizer/prep/prepunion.c index fb4fd3e1d3..414e26c54c 100644 --- a/src/backend/optimizer/prep/prepunion.c +++ b/src/backend/optimizer/prep/prepunion.c @@ -14,7 +14,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/prep/prepunion.c,v 1.78 2002/09/04 20:31:22 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/prep/prepunion.c,v 1.79 2002/09/11 14:48:55 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -774,7 +774,7 @@ adjust_inherited_attrs(Node *node, if (newnode->resultRelation == old_rt_index) newnode->resultRelation = new_rt_index; query_tree_mutator(newnode, adjust_inherited_attrs_mutator, - (void *) &context, false); + (void *) &context, QTW_IGNORE_SUBQUERIES); return (Node *) newnode; } else diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c index edf77faff0..ee03797476 100644 --- a/src/backend/optimizer/util/clauses.c +++ b/src/backend/optimizer/util/clauses.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.108 2002/09/04 20:31:22 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.109 2002/09/11 14:48:54 tgl Exp $ * * HISTORY * AUTHOR DATE MAJOR EVENT @@ -1788,7 +1788,7 @@ simplify_op_or_func(Expr *expr, List *args) * { * adjust context for subquery; * result = query_tree_walker((Query *) node, my_walker, context, - * true); // to visit subquery RTEs too + * 0); // to visit rtable items too * restore context if needed; * return result; * } @@ -1994,16 +1994,17 @@ expression_tree_walker(Node *node, * walker intends to descend into subqueries. It is also useful for * descending into subqueries within a walker. * - * If visitQueryRTEs is true, the walker will also be called on sub-Query - * nodes present in subquery rangetable entries of the given Query. This - * is optional since some callers handle those sub-queries separately, - * or don't really want to see subqueries anyway. + * Some callers want to suppress visitation of certain items in the sub-Query, + * typically because they need to process them specially, or don't actually + * want to recurse into subqueries. This is supported by the flags argument, + * which is the bitwise OR of flag values to suppress visitation of + * indicated items. (More flag bits may be added as needed.) */ bool query_tree_walker(Query *query, bool (*walker) (), void *context, - bool visitQueryRTEs) + int flags) { List *rt; @@ -2028,13 +2029,14 @@ query_tree_walker(Query *query, /* nothing to do */ break; case RTE_SUBQUERY: - if (visitQueryRTEs) + if (! (flags & QTW_IGNORE_SUBQUERIES)) if (walker(rte->subquery, context)) return true; break; case RTE_JOIN: - if (walker(rte->joinaliasvars, context)) - return true; + if (! (flags & QTW_IGNORE_JOINALIASES)) + if (walker(rte->joinaliasvars, context)) + return true; break; case RTE_FUNCTION: if (walker(rte->funcexpr, context)) @@ -2388,16 +2390,17 @@ expression_tree_mutator(Node *node, * if you don't want to change the original. All substructure is safely * copied, however. * - * If visitQueryRTEs is true, the mutator will also be called on sub-Query - * nodes present in subquery rangetable entries of the given Query. This - * is optional since some callers handle those sub-queries separately, - * or don't really want to see subqueries anyway. + * 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 + * want to recurse into subqueries. This is supported by the flags argument, + * which is the bitwise OR of flag values to suppress mutating of + * indicated items. (More flag bits may be added as needed.) */ void query_tree_mutator(Query *query, Node *(*mutator) (), void *context, - bool visitQueryRTEs) + int flags) { List *newrt = NIL; List *rt; @@ -2420,7 +2423,7 @@ query_tree_mutator(Query *query, /* nothing to do, don't bother to make a copy */ break; case RTE_SUBQUERY: - if (visitQueryRTEs) + if (! (flags & QTW_IGNORE_SUBQUERIES)) { FLATCOPY(newrte, rte, RangeTblEntry); CHECKFLATCOPY(newrte->subquery, rte->subquery, Query); @@ -2429,9 +2432,12 @@ query_tree_mutator(Query *query, } break; case RTE_JOIN: - FLATCOPY(newrte, rte, RangeTblEntry); - MUTATE(newrte->joinaliasvars, rte->joinaliasvars, List *); - rte = newrte; + if (! (flags & QTW_IGNORE_JOINALIASES)) + { + FLATCOPY(newrte, rte, RangeTblEntry); + MUTATE(newrte->joinaliasvars, rte->joinaliasvars, List *); + rte = newrte; + } break; case RTE_FUNCTION: FLATCOPY(newrte, rte, RangeTblEntry); diff --git a/src/backend/optimizer/util/var.c b/src/backend/optimizer/util/var.c index ccccdbf180..23b824dbcb 100644 --- a/src/backend/optimizer/util/var.c +++ b/src/backend/optimizer/util/var.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/util/var.c,v 1.39 2002/09/04 20:31:22 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/util/var.c,v 1.40 2002/09/11 14:48:54 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -82,7 +82,7 @@ pull_varnos(Node *node) */ if (node && IsA(node, Query)) query_tree_walker((Query *) node, pull_varnos_walker, - (void *) &context, true); + (void *) &context, 0); else pull_varnos_walker(node, &context); @@ -128,7 +128,7 @@ pull_varnos_walker(Node *node, pull_varnos_context *context) context->sublevels_up++; result = query_tree_walker((Query *) node, pull_varnos_walker, - (void *) context, true); + (void *) context, 0); context->sublevels_up--; return result; } @@ -165,7 +165,7 @@ contain_var_reference(Node *node, int varno, int varattno, int levelsup) if (node && IsA(node, Query)) return query_tree_walker((Query *) node, contain_var_reference_walker, - (void *) &context, true); + (void *) &context, 0); else return contain_var_reference_walker(node, &context); } @@ -212,7 +212,7 @@ contain_var_reference_walker(Node *node, context->sublevels_up++; result = query_tree_walker((Query *) node, contain_var_reference_walker, - (void *) context, true); + (void *) context, 0); context->sublevels_up--; return result; } diff --git a/src/backend/rewrite/rewriteDefine.c b/src/backend/rewrite/rewriteDefine.c index 2aa4fdd892..1933482faa 100644 --- a/src/backend/rewrite/rewriteDefine.c +++ b/src/backend/rewrite/rewriteDefine.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteDefine.c,v 1.79 2002/09/04 20:31:25 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteDefine.c,v 1.80 2002/09/11 14:48:54 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -464,9 +464,10 @@ setRuleCheckAsUser(Query *qry, Oid userid) } /* If there are sublinks, search for them and process their RTEs */ + /* ignore subqueries in rtable because we already processed them */ if (qry->hasSubLinks) query_tree_walker(qry, setRuleCheckAsUser_walker, (void *) &userid, - false /* already did the ones in rtable */ ); + QTW_IGNORE_SUBQUERIES); } /* diff --git a/src/backend/rewrite/rewriteHandler.c b/src/backend/rewrite/rewriteHandler.c index d434e9e2fb..95fc726227 100644 --- a/src/backend/rewrite/rewriteHandler.c +++ b/src/backend/rewrite/rewriteHandler.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.108 2002/09/04 20:31:25 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.109 2002/09/11 14:48:54 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -822,11 +822,12 @@ fireRIRrules(Query *parsetree) } /* - * Recurse into sublink subqueries, too. + * Recurse into sublink subqueries, too. But we already did the ones + * in the rtable. */ if (parsetree->hasSubLinks) query_tree_walker(parsetree, fireRIRonSubLink, NULL, - false /* already handled the ones in rtable */ ); + QTW_IGNORE_SUBQUERIES); /* * If the query was marked having aggregates, check if this is still diff --git a/src/backend/rewrite/rewriteManip.c b/src/backend/rewrite/rewriteManip.c index 16eef1bfb8..12154b8da6 100644 --- a/src/backend/rewrite/rewriteManip.c +++ b/src/backend/rewrite/rewriteManip.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteManip.c,v 1.65 2002/09/04 20:31:25 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteManip.c,v 1.66 2002/09/11 14:48:54 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -49,7 +49,7 @@ checkExprHasAggs(Node *node) */ if (node && IsA(node, Query)) return query_tree_walker((Query *) node, checkExprHasAggs_walker, - NULL, false); + NULL, QTW_IGNORE_SUBQUERIES); else return checkExprHasAggs_walker(node, NULL); } @@ -79,7 +79,7 @@ checkExprHasSubLink(Node *node) */ if (node && IsA(node, Query)) return query_tree_walker((Query *) node, checkExprHasSubLink_walker, - NULL, false); + NULL, QTW_IGNORE_SUBQUERIES); else return checkExprHasSubLink_walker(node, NULL); } @@ -155,7 +155,7 @@ OffsetVarNodes_walker(Node *node, OffsetVarNodes_context *context) context->sublevels_up++; result = query_tree_walker((Query *) node, OffsetVarNodes_walker, - (void *) context, true); + (void *) context, 0); context->sublevels_up--; return result; } @@ -196,7 +196,7 @@ OffsetVarNodes(Node *node, int offset, int sublevels_up) lfirsti(l) += offset; } query_tree_walker(qry, OffsetVarNodes_walker, - (void *) &context, true); + (void *) &context, 0); } else OffsetVarNodes_walker(node, &context); @@ -265,7 +265,7 @@ ChangeVarNodes_walker(Node *node, ChangeVarNodes_context *context) context->sublevels_up++; result = query_tree_walker((Query *) node, ChangeVarNodes_walker, - (void *) context, true); + (void *) context, 0); context->sublevels_up--; return result; } @@ -310,7 +310,7 @@ ChangeVarNodes(Node *node, int rt_index, int new_index, int sublevels_up) } } query_tree_walker(qry, ChangeVarNodes_walker, - (void *) &context, true); + (void *) &context, 0); } else ChangeVarNodes_walker(node, &context); @@ -361,7 +361,7 @@ IncrementVarSublevelsUp_walker(Node *node, context->min_sublevels_up++; result = query_tree_walker((Query *) node, IncrementVarSublevelsUp_walker, - (void *) context, true); + (void *) context, 0); context->min_sublevels_up--; return result; } @@ -385,7 +385,7 @@ IncrementVarSublevelsUp(Node *node, int delta_sublevels_up, */ if (node && IsA(node, Query)) query_tree_walker((Query *) node, IncrementVarSublevelsUp_walker, - (void *) &context, true); + (void *) &context, 0); else IncrementVarSublevelsUp_walker(node, &context); } @@ -443,7 +443,7 @@ rangeTableEntry_used_walker(Node *node, context->sublevels_up++; result = query_tree_walker((Query *) node, rangeTableEntry_used_walker, - (void *) context, true); + (void *) context, 0); context->sublevels_up--; return result; } @@ -466,7 +466,7 @@ rangeTableEntry_used(Node *node, int rt_index, int sublevels_up) */ if (node && IsA(node, Query)) return query_tree_walker((Query *) node, rangeTableEntry_used_walker, - (void *) &context, true); + (void *) &context, 0); else return rangeTableEntry_used_walker(node, &context); } @@ -508,7 +508,7 @@ attribute_used_walker(Node *node, context->sublevels_up++; result = query_tree_walker((Query *) node, attribute_used_walker, - (void *) context, true); + (void *) context, 0); context->sublevels_up--; return result; } @@ -532,7 +532,7 @@ attribute_used(Node *node, int rt_index, int attno, int sublevels_up) */ if (node && IsA(node, Query)) return query_tree_walker((Query *) node, attribute_used_walker, - (void *) &context, true); + (void *) &context, 0); else return attribute_used_walker(node, &context); } @@ -851,7 +851,7 @@ ResolveNew_mutator(Node *node, ResolveNew_context *context) FLATCOPY(newnode, query, Query); context->sublevels_up++; - query_tree_mutator(newnode, ResolveNew_mutator, context, true); + query_tree_mutator(newnode, ResolveNew_mutator, context, 0); context->sublevels_up--; return (Node *) newnode; } @@ -883,7 +883,7 @@ ResolveNew(Node *node, int target_varno, int sublevels_up, FLATCOPY(newnode, query, Query); query_tree_mutator(newnode, ResolveNew_mutator, - (void *) &context, true); + (void *) &context, 0); return (Node *) newnode; } else @@ -991,7 +991,7 @@ HandleRIRAttributeRule_mutator(Node *node, FLATCOPY(newnode, query, Query); context->sublevels_up++; query_tree_mutator(newnode, HandleRIRAttributeRule_mutator, - context, true); + context, 0); context->sublevels_up--; return (Node *) newnode; } @@ -1019,7 +1019,7 @@ HandleRIRAttributeRule(Query *parsetree, context.sublevels_up = 0; query_tree_mutator(parsetree, HandleRIRAttributeRule_mutator, - (void *) &context, true); + (void *) &context, 0); } #endif /* NOT_USED */ diff --git a/src/include/optimizer/clauses.h b/src/include/optimizer/clauses.h index 7c36586a34..844e7d9490 100644 --- a/src/include/optimizer/clauses.h +++ b/src/include/optimizer/clauses.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: clauses.h,v 1.53 2002/06/20 20:29:51 momjian Exp $ + * $Id: clauses.h,v 1.54 2002/09/11 14:48:55 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -66,10 +66,15 @@ extern bool expression_tree_walker(Node *node, bool (*walker) (), void *context); extern Node *expression_tree_mutator(Node *node, Node *(*mutator) (), void *context); + +/* flags bits for query_tree_walker and query_tree_mutator */ +#define QTW_IGNORE_SUBQUERIES 0x01 /* subqueries in rtable */ +#define QTW_IGNORE_JOINALIASES 0x02 /* JOIN alias var lists */ + extern bool query_tree_walker(Query *query, bool (*walker) (), - void *context, bool visitQueryRTEs); + void *context, int flags); extern void query_tree_mutator(Query *query, Node *(*mutator) (), - void *context, bool visitQueryRTEs); + void *context, int flags); #define is_subplan(clause) ((clause) != NULL && \ IsA(clause, Expr) && \