diff options
Diffstat (limited to 'src/backend/optimizer/util')
-rw-r--r-- | src/backend/optimizer/util/clauses.c | 521 | ||||
-rw-r--r-- | src/backend/optimizer/util/pathnode.c | 65 | ||||
-rw-r--r-- | src/backend/optimizer/util/plancat.c | 42 | ||||
-rw-r--r-- | src/backend/optimizer/util/relnode.c | 81 | ||||
-rw-r--r-- | src/backend/optimizer/util/tlist.c | 14 | ||||
-rw-r--r-- | src/backend/optimizer/util/var.c | 17 |
6 files changed, 412 insertions, 328 deletions
diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c index d429db93a03..7ddbe4190cc 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.64 2000/04/04 01:21:46 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.65 2000/04/12 17:15:24 momjian Exp $ * * HISTORY * AUTHOR DATE MAJOR EVENT @@ -46,9 +46,9 @@ static bool pull_agg_clause_walker(Node *node, List **listptr); static bool contain_subplans_walker(Node *node, void *context); static bool pull_subplans_walker(Node *node, List **listptr); static bool check_subplans_for_ungrouped_vars_walker(Node *node, - Query *context); -static int is_single_func(Node *node); -static Node *eval_const_expressions_mutator (Node *node, void *context); + Query *context); +static int is_single_func(Node *node); +static Node *eval_const_expressions_mutator(Node *node, void *context); static Expr *simplify_op_or_func(Expr *expr, List *args); @@ -340,18 +340,19 @@ make_ands_explicit(List *andclauses) List * make_ands_implicit(Expr *clause) { + /* * NB: because the parser sets the qual field to NULL in a query that * has no WHERE clause, we must consider a NULL input clause as TRUE, - * even though one might more reasonably think it FALSE. Grumble. - * If this causes trouble, consider changing the parser's behavior. + * even though one might more reasonably think it FALSE. Grumble. If + * this causes trouble, consider changing the parser's behavior. */ if (clause == NULL) return NIL; /* NULL -> NIL list == TRUE */ else if (and_clause((Node *) clause)) return clause->args; else if (IsA(clause, Const) && - ! ((Const *) clause)->constisnull && + !((Const *) clause)->constisnull && DatumGetInt32(((Const *) clause)->constvalue)) return NIL; /* constant TRUE input -> NIL list */ else @@ -381,7 +382,8 @@ contain_agg_clause_walker(Node *node, void *context) if (node == NULL) return false; if (IsA(node, Aggref)) - return true; /* abort the tree traversal and return true */ + return true; /* abort the tree traversal and return + * true */ return expression_tree_walker(node, contain_agg_clause_walker, context); } @@ -411,12 +413,14 @@ pull_agg_clause_walker(Node *node, List **listptr) if (IsA(node, Aggref)) { *listptr = lappend(*listptr, node); + /* * Complain if the aggregate's argument contains any aggregates; * nested agg functions are semantically nonsensical. */ if (contain_agg_clause(((Aggref *) node)->target)) elog(ERROR, "Aggregate function calls may not be nested"); + /* * Having checked that, we need not recurse into the argument. */ @@ -454,7 +458,8 @@ contain_subplans_walker(Node *node, void *context) if (node == NULL) return false; if (is_subplan(node) || IsA(node, SubLink)) - return true; /* abort the tree traversal and return true */ + return true; /* abort the tree traversal and return + * true */ return expression_tree_walker(node, contain_subplans_walker, context); } @@ -462,7 +467,7 @@ contain_subplans_walker(Node *node, void *context) * pull_subplans * Recursively pulls all subplans from an expression tree. * - * Returns list of subplan nodes found. Note the nodes themselves are not + * Returns list of subplan nodes found. Note the nodes themselves are not * copied, only referenced. */ List * @@ -507,7 +512,11 @@ void check_subplans_for_ungrouped_vars(Node *clause, Query *query) { - /* No special setup needed; context for walker is just the Query pointer */ + + /* + * No special setup needed; context for walker is just the Query + * pointer + */ check_subplans_for_ungrouped_vars_walker(clause, query); } @@ -517,17 +526,19 @@ check_subplans_for_ungrouped_vars_walker(Node *node, { if (node == NULL) return false; + /* - * We can ignore Vars other than in subplan args lists, - * since the parser already checked 'em. + * 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. */ - List *t; + List *t; foreach(t, ((Expr *) node)->args) { @@ -539,10 +550,10 @@ check_subplans_for_ungrouped_vars_walker(Node *node, /* * We do not care about args that are not local variables; * params or outer-level vars are not our responsibility to - * check. (The outer-level query passing them to us needs - * to worry, instead.) + * check. (The outer-level query passing them to us needs to + * worry, instead.) */ - if (! IsA(thisarg, Var)) + if (!IsA(thisarg, Var)) continue; var = (Var *) thisarg; if (var->varlevelsup > 0) @@ -554,8 +565,8 @@ check_subplans_for_ungrouped_vars_walker(Node *node, contained_in_group_clause = false; foreach(gl, context->groupClause) { - GroupClause *gcl = lfirst(gl); - Node *groupexpr; + GroupClause *gcl = lfirst(gl); + Node *groupexpr; groupexpr = get_sortgroupclause_expr(gcl, context->targetList); @@ -569,14 +580,14 @@ check_subplans_for_ungrouped_vars_walker(Node *node, if (!contained_in_group_clause) { /* Found an ungrouped argument. Complain. */ - RangeTblEntry *rte; - char *attname; + RangeTblEntry *rte; + char *attname; Assert(var->varno > 0 && var->varno <= length(context->rtable)); rte = rt_fetch(var->varno, context->rtable); attname = get_attname(rte->relid, var->varattno); - if (! attname) + if (!attname) elog(ERROR, "cache lookup of attribute %d in relation %u failed", var->varattno, rte->relid); elog(ERROR, "Sub-SELECT uses un-GROUPed attribute %s.%s from outer query", @@ -585,7 +596,7 @@ check_subplans_for_ungrouped_vars_walker(Node *node, } } return expression_tree_walker(node, - check_subplans_for_ungrouped_vars_walker, + check_subplans_for_ungrouped_vars_walker, (void *) context); } @@ -697,7 +708,7 @@ NumRelids(Node *clause) * is referenced in the clause). The routine checks that the * expression is of the form (var op something) or (something op var) * where the var is an attribute of the specified relation, or - * a function of a var of the specified relation. If so, it + * a function of a var of the specified relation. If so, it * returns the following info: * the found relation number (same as targetrelid unless that is 0) * the found var number (or InvalidAttrNumber if a function) @@ -707,7 +718,7 @@ NumRelids(Node *clause) * specifically 0 for the relid and attno, 0 for the constant value. * * Note that negative attno values are *not* invalid, but represent - * system attributes such as OID. It's sufficient to check for relid=0 + * system attributes such as OID. It's sufficient to check for relid=0 * to determine whether the routine succeeded. */ void @@ -785,15 +796,13 @@ default_results: *flag |= SEL_CONSTANT; } else - { *constval = 0; - } } /* * is_single_func - * If the given expression is a function of a single relation, - * return the relation number; else return 0 + * If the given expression is a function of a single relation, + * return the relation number; else return 0 */ static int is_single_func(Node *node) @@ -804,7 +813,7 @@ is_single_func(Node *node) if (length(varnos) == 1) { - int funcvarno = lfirsti(varnos); + int funcvarno = lfirsti(varnos); freeList(varnos); return funcvarno; @@ -922,7 +931,7 @@ CommuteClause(Expr *clause) * expression tree, for example "2 + 2" => "4". More interestingly, * we can reduce certain boolean expressions even when they contain * non-constant subexpressions: "x OR true" => "true" no matter what - * the subexpression x is. (XXX We assume that no such subexpression + * the subexpression x is. (XXX We assume that no such subexpression * will have important side-effects, which is not necessarily a good * assumption in the presence of user-defined functions; do we need a * pg_proc flag that prevents discarding the execution of a function?) @@ -954,7 +963,7 @@ eval_const_expressions(Node *node) } static Node * -eval_const_expressions_mutator (Node *node, void *context) +eval_const_expressions_mutator(Node *node, void *context) { if (node == NULL) return NULL; @@ -963,21 +972,22 @@ eval_const_expressions_mutator (Node *node, void *context) Expr *expr = (Expr *) node; List *args; Const *const_input; - Expr *newexpr; + Expr *newexpr; /* * Reduce constants in the Expr's arguments. We know args is - * either NIL or a List node, so we can call expression_tree_mutator - * directly rather than recursing to self. + * either NIL or a List node, so we can call + * expression_tree_mutator directly rather than recursing to self. */ args = (List *) expression_tree_mutator((Node *) expr->args, - eval_const_expressions_mutator, + eval_const_expressions_mutator, (void *) context); switch (expr->opType) { case OP_EXPR: case FUNC_EXPR: + /* * Code for op/func case is pretty bulky, so split it out * as a separate function. @@ -985,123 +995,131 @@ eval_const_expressions_mutator (Node *node, void *context) newexpr = simplify_op_or_func(expr, args); if (newexpr) /* successfully simplified it */ return (Node *) newexpr; - /* else fall out to build new Expr node with simplified args */ - break; - case OR_EXPR: - { + /* - * OR arguments are handled as follows: - * non constant: keep - * FALSE: drop (does not affect result) - * TRUE: force result to TRUE - * NULL: keep only one - * We keep one NULL input because ExecEvalOr returns - * NULL when no input is TRUE and at least one is NULL. + * else fall out to build new Expr node with simplified + * args */ - List *newargs = NIL; - List *arg; - bool haveNull = false; - bool forceTrue = false; - - foreach(arg, args) + break; + case OR_EXPR: { - if (! IsA(lfirst(arg), Const)) + + /* + * OR arguments are handled as follows: non constant: + * keep FALSE: drop (does not affect result) TRUE: + * force result to TRUE NULL: keep only one We keep + * one NULL input because ExecEvalOr returns NULL when + * no input is TRUE and at least one is NULL. + */ + List *newargs = NIL; + List *arg; + bool haveNull = false; + bool forceTrue = false; + + foreach(arg, args) { - newargs = lappend(newargs, lfirst(arg)); - continue; + if (!IsA(lfirst(arg), Const)) + { + newargs = lappend(newargs, lfirst(arg)); + continue; + } + const_input = (Const *) lfirst(arg); + if (const_input->constisnull) + haveNull = true; + else if (DatumGetInt32(const_input->constvalue)) + forceTrue = true; + /* otherwise, we can drop the constant-false input */ } - const_input = (Const *) lfirst(arg); - if (const_input->constisnull) - haveNull = true; - else if (DatumGetInt32(const_input->constvalue)) - forceTrue = true; - /* otherwise, we can drop the constant-false input */ + + /* + * We could return TRUE before falling out of the + * loop, but this coding method will be easier to + * adapt if we ever add a notion of non-removable + * functions. We'd need to check all the inputs for + * non-removability. + */ + if (forceTrue) + return MAKEBOOLCONST(true, false); + if (haveNull) + newargs = lappend(newargs, MAKEBOOLCONST(false, true)); + /* If all the inputs are FALSE, result is FALSE */ + if (newargs == NIL) + return MAKEBOOLCONST(false, false); + /* If only one nonconst-or-NULL input, it's the result */ + if (lnext(newargs) == NIL) + return (Node *) lfirst(newargs); + /* Else we still need an OR node */ + return (Node *) make_orclause(newargs); } - /* - * We could return TRUE before falling out of the loop, - * but this coding method will be easier to adapt if - * we ever add a notion of non-removable functions. - * We'd need to check all the inputs for non-removability. - */ - if (forceTrue) - return MAKEBOOLCONST(true, false); - if (haveNull) - newargs = lappend(newargs, MAKEBOOLCONST(false, true)); - /* If all the inputs are FALSE, result is FALSE */ - if (newargs == NIL) - return MAKEBOOLCONST(false, false); - /* If only one nonconst-or-NULL input, it's the result */ - if (lnext(newargs) == NIL) - return (Node *) lfirst(newargs); - /* Else we still need an OR node */ - return (Node *) make_orclause(newargs); - } case AND_EXPR: - { - /* - * AND arguments are handled as follows: - * non constant: keep - * TRUE: drop (does not affect result) - * FALSE: force result to FALSE - * NULL: keep only one - * We keep one NULL input because ExecEvalAnd returns - * NULL when no input is FALSE and at least one is NULL. - */ - List *newargs = NIL; - List *arg; - bool haveNull = false; - bool forceFalse = false; - - foreach(arg, args) { - if (! IsA(lfirst(arg), Const)) + + /* + * AND arguments are handled as follows: non constant: + * keep TRUE: drop (does not affect result) FALSE: + * force result to FALSE NULL: keep only one We keep + * one NULL input because ExecEvalAnd returns NULL + * when no input is FALSE and at least one is NULL. + */ + List *newargs = NIL; + List *arg; + bool haveNull = false; + bool forceFalse = false; + + foreach(arg, args) { - newargs = lappend(newargs, lfirst(arg)); - continue; + if (!IsA(lfirst(arg), Const)) + { + newargs = lappend(newargs, lfirst(arg)); + continue; + } + const_input = (Const *) lfirst(arg); + if (const_input->constisnull) + haveNull = true; + else if (!DatumGetInt32(const_input->constvalue)) + forceFalse = true; + /* otherwise, we can drop the constant-true input */ } - const_input = (Const *) lfirst(arg); - if (const_input->constisnull) - haveNull = true; - else if (! DatumGetInt32(const_input->constvalue)) - forceFalse = true; - /* otherwise, we can drop the constant-true input */ + + /* + * We could return FALSE before falling out of the + * loop, but this coding method will be easier to + * adapt if we ever add a notion of non-removable + * functions. We'd need to check all the inputs for + * non-removability. + */ + if (forceFalse) + return MAKEBOOLCONST(false, false); + if (haveNull) + newargs = lappend(newargs, MAKEBOOLCONST(false, true)); + /* If all the inputs are TRUE, result is TRUE */ + if (newargs == NIL) + return MAKEBOOLCONST(true, false); + /* If only one nonconst-or-NULL input, it's the result */ + if (lnext(newargs) == NIL) + return (Node *) lfirst(newargs); + /* Else we still need an AND node */ + return (Node *) make_andclause(newargs); } - /* - * We could return FALSE before falling out of the loop, - * but this coding method will be easier to adapt if - * we ever add a notion of non-removable functions. - * We'd need to check all the inputs for non-removability. - */ - if (forceFalse) - return MAKEBOOLCONST(false, false); - if (haveNull) - newargs = lappend(newargs, MAKEBOOLCONST(false, true)); - /* If all the inputs are TRUE, result is TRUE */ - if (newargs == NIL) - return MAKEBOOLCONST(true, false); - /* If only one nonconst-or-NULL input, it's the result */ - if (lnext(newargs) == NIL) - return (Node *) lfirst(newargs); - /* Else we still need an AND node */ - return (Node *) make_andclause(newargs); - } case NOT_EXPR: Assert(length(args) == 1); - if (! IsA(lfirst(args), Const)) + if (!IsA(lfirst(args), Const)) break; const_input = (Const *) lfirst(args); /* NOT NULL => NULL */ if (const_input->constisnull) return MAKEBOOLCONST(false, true); /* otherwise pretty easy */ - return MAKEBOOLCONST(! DatumGetInt32(const_input->constvalue), + return MAKEBOOLCONST(!DatumGetInt32(const_input->constvalue), false); case SUBPLAN_EXPR: + /* * Safety measure per notes at head of this routine: - * return a SubPlan unchanged. Too late to do anything + * return a SubPlan unchanged. Too late to do anything * with it. The arglist simplification above was wasted - * work (the list probably only contains Var nodes anyway). + * work (the list probably only contains Var nodes + * anyway). */ return (Node *) expr; default: @@ -1112,25 +1130,26 @@ eval_const_expressions_mutator (Node *node, void *context) /* * If we break out of the above switch on opType, then the - * expression cannot be simplified any further, so build - * and return a replacement Expr node using the - * possibly-simplified arguments and the original oper node. - * Can't use make_clause() here because we want to be sure - * the typeOid field is preserved... + * expression cannot be simplified any further, so build and + * return a replacement Expr node using the possibly-simplified + * arguments and the original oper node. Can't use make_clause() + * here because we want to be sure the typeOid field is + * preserved... */ newexpr = makeNode(Expr); - newexpr->typeOid = expr->typeOid; - newexpr->opType = expr->opType; - newexpr->oper = expr->oper; - newexpr->args = args; - return (Node *) newexpr; + newexpr->typeOid = expr->typeOid; + newexpr->opType = expr->opType; + newexpr->oper = expr->oper; + newexpr->args = args; + return (Node *) newexpr; } if (IsA(node, RelabelType)) { + /* * If we can simplify the input to a constant, then we don't need - * the RelabelType node anymore: just change the type field of - * the Const node. Otherwise, copy the RelabelType node. + * the RelabelType node anymore: just change the type field of the + * Const node. Otherwise, copy the RelabelType node. */ RelabelType *relabel = (RelabelType *) node; Node *arg; @@ -1138,13 +1157,15 @@ eval_const_expressions_mutator (Node *node, void *context) arg = eval_const_expressions_mutator(relabel->arg, context); if (arg && IsA(arg, Const)) { - Const *con = (Const *) arg; + Const *con = (Const *) arg; con->consttype = relabel->resulttype; + /* * relabel's resulttypmod is discarded, which is OK for now; * if the type actually needs a runtime length coercion then - * there should be a function call to do it just above this node. + * there should be a function call to do it just above this + * node. */ return (Node *) con; } @@ -1160,15 +1181,15 @@ eval_const_expressions_mutator (Node *node, void *context) } if (IsA(node, CaseExpr)) { + /* - * CASE expressions can be simplified if there are constant condition - * clauses: - * FALSE (or NULL): drop the alternative - * TRUE: drop all remaining alternatives - * If the first non-FALSE alternative is a constant TRUE, we can - * simplify the entire CASE to that alternative's expression. - * If there are no non-FALSE alternatives, we simplify the entire - * CASE to the default result (ELSE result). + * CASE expressions can be simplified if there are constant + * condition clauses: FALSE (or NULL): drop the alternative TRUE: + * drop all remaining alternatives If the first non-FALSE + * alternative is a constant TRUE, we can simplify the entire CASE + * to that alternative's expression. If there are no non-FALSE + * alternatives, we simplify the entire CASE to the default result + * (ELSE result). */ CaseExpr *caseexpr = (CaseExpr *) node; CaseExpr *newcase; @@ -1181,26 +1202,29 @@ eval_const_expressions_mutator (Node *node, void *context) { /* Simplify this alternative's condition and result */ CaseWhen *casewhen = (CaseWhen *) - expression_tree_mutator((Node *) lfirst(arg), - eval_const_expressions_mutator, - (void *) context); + expression_tree_mutator((Node *) lfirst(arg), + eval_const_expressions_mutator, + (void *) context); + Assert(IsA(casewhen, CaseWhen)); if (casewhen->expr == NULL || - ! IsA(casewhen->expr, Const)) + !IsA(casewhen->expr, Const)) { newargs = lappend(newargs, casewhen); continue; } const_input = (Const *) casewhen->expr; if (const_input->constisnull || - ! DatumGetInt32(const_input->constvalue)) + !DatumGetInt32(const_input->constvalue)) continue; /* drop alternative with FALSE condition */ + /* - * Found a TRUE condition. If it's the first (un-dropped) + * Found a TRUE condition. If it's the first (un-dropped) * alternative, the CASE reduces to just this alternative. */ if (newargs == NIL) return casewhen->result; + /* * Otherwise, add it to the list, and drop all the rest. */ @@ -1211,7 +1235,11 @@ eval_const_expressions_mutator (Node *node, void *context) /* Simplify the default result */ defresult = eval_const_expressions_mutator(caseexpr->defresult, context); - /* If no non-FALSE alternatives, CASE reduces to the default result */ + + /* + * If no non-FALSE alternatives, CASE reduces to the default + * result + */ if (newargs == NIL) return defresult; /* Otherwise we need a new CASE node */ @@ -1224,21 +1252,21 @@ eval_const_expressions_mutator (Node *node, void *context) } if (IsA(node, Iter)) { + /* - * The argument of an Iter is normally a function call. - * We must not try to eliminate the function, but we - * can try to simplify its arguments. If, by chance, - * the arg is NOT a function then we go ahead and try to - * simplify it (by falling into expression_tree_mutator). - * Is that the right thing? + * The argument of an Iter is normally a function call. We must + * not try to eliminate the function, but we can try to simplify + * its arguments. If, by chance, the arg is NOT a function then + * we go ahead and try to simplify it (by falling into + * expression_tree_mutator). Is that the right thing? */ Iter *iter = (Iter *) node; if (is_funcclause(iter->iterexpr)) { - Expr *func = (Expr *) iter->iterexpr; - Expr *newfunc; - Iter *newiter; + Expr *func = (Expr *) iter->iterexpr; + Expr *newfunc; + Iter *newiter; newfunc = makeNode(Expr); newfunc->typeOid = func->typeOid; @@ -1254,12 +1282,13 @@ eval_const_expressions_mutator (Node *node, void *context) return (Node *) newiter; } } + /* * For any node type not handled above, we recurse using - * expression_tree_mutator, which will copy the node unchanged - * but try to simplify its arguments (if any) using this routine. - * For example: we cannot eliminate an ArrayRef node, but we - * might be able to simplify constant expressions in its subscripts. + * expression_tree_mutator, which will copy the node unchanged but try + * to simplify its arguments (if any) using this routine. For example: + * we cannot eliminate an ArrayRef node, but we might be able to + * simplify constant expressions in its subscripts. */ return expression_tree_mutator(node, eval_const_expressions_mutator, (void *) context); @@ -1289,31 +1318,32 @@ simplify_op_or_func(Expr *expr, List *args) HeapTuple func_tuple; Form_pg_proc funcform; Type resultType; - Expr *newexpr; + Expr *newexpr; Datum const_val; bool const_is_null; bool isDone; /* - * For an operator or function, we cannot simplify unless all the inputs - * are constants. (XXX possible future improvement: if the op/func is - * strict and at least one input is NULL, we could simplify to NULL. - * But we do not currently have any way to know if the op/func is strict - * or not. For now, a NULL input is treated the same as any other - * constant node.) + * For an operator or function, we cannot simplify unless all the + * inputs are constants. (XXX possible future improvement: if the + * op/func is strict and at least one input is NULL, we could simplify + * to NULL. But we do not currently have any way to know if the + * op/func is strict or not. For now, a NULL input is treated the + * same as any other constant node.) */ foreach(arg, args) { - if (! IsA(lfirst(arg), Const)) + if (!IsA(lfirst(arg), Const)) return NULL; } + /* - * Get the function procedure's OID and look to see - * whether it is marked proiscachable. + * Get the function procedure's OID and look to see whether it is + * marked proiscachable. */ if (expr->opType == OP_EXPR) { - Oper *oper = (Oper *) expr->oper; + Oper *oper = (Oper *) expr->oper; replace_opid(oper); /* OK to scribble on input to this extent */ funcid = oper->opid; @@ -1321,7 +1351,7 @@ simplify_op_or_func(Expr *expr, List *args) } else { - Func *func = (Func *) expr->oper; + Func *func = (Func *) expr->oper; funcid = func->funcid; result_typeid = func->functype; @@ -1333,21 +1363,23 @@ simplify_op_or_func(Expr *expr, List *args) if (!HeapTupleIsValid(func_tuple)) elog(ERROR, "Function OID %u does not exist", funcid); funcform = (Form_pg_proc) GETSTRUCT(func_tuple); - if (! funcform->proiscachable) + if (!funcform->proiscachable) return NULL; + /* * Also check to make sure it doesn't return a set. */ if (funcform->proretset) return NULL; + /* * OK, looks like we can simplify this operator/function. * * We use the executor's routine ExecEvalExpr() to avoid duplication of * code and ensure we get the same result as the executor would get. * - * Build a new Expr node containing the already-simplified arguments. - * The only other setup needed here is the replace_opid() that we already + * Build a new Expr node containing the already-simplified arguments. The + * only other setup needed here is the replace_opid() that we already * did for the OP_EXPR case. */ newexpr = makeNode(Expr); @@ -1355,21 +1387,23 @@ simplify_op_or_func(Expr *expr, List *args) newexpr->opType = expr->opType; newexpr->oper = expr->oper; newexpr->args = args; + /* * It is OK to pass econtext = NULL because none of the ExecEvalExpr() * code used in this situation will use econtext. That might seem - * fortuitous, but it's not so unreasonable --- a constant expression does - * not depend on context, by definition, n'est ce pas? + * fortuitous, but it's not so unreasonable --- a constant expression + * does not depend on context, by definition, n'est ce pas? */ const_val = ExecEvalExpr((Node *) newexpr, NULL, &const_is_null, &isDone); Assert(isDone); /* if this isn't set, we blew it... */ pfree(newexpr); + /* * Make the constant result node. * - * XXX would it be better to take the result type from the - * pg_proc tuple, rather than the Oper or Func node? + * XXX would it be better to take the result type from the pg_proc tuple, + * rather than the Oper or Func node? */ resultType = typeidType(result_typeid); return (Expr *) makeConst(result_typeid, typeLen(resultType), @@ -1426,8 +1460,8 @@ simplify_op_or_func(Expr *expr, List *args) * * The walker routine should return "false" to continue the tree walk, or * "true" to abort the walk and immediately return "true" to the top-level - * caller. This can be used to short-circuit the traversal if the walker - * has found what it came for. "false" is returned to the top-level caller + * caller. This can be used to short-circuit the traversal if the walker + * has found what it came for. "false" is returned to the top-level caller * iff no invocation of the walker returned "true". * * The node types handled by expression_tree_walker include all those @@ -1454,16 +1488,16 @@ simplify_op_or_func(Expr *expr, List *args) */ bool -expression_tree_walker(Node *node, bool (*walker) (), void *context) + expression_tree_walker(Node *node, bool (*walker) (), void *context) { List *temp; /* - * The walker has already visited the current node, - * and so we need only recurse into any sub-nodes it has. + * The walker has already visited the current node, and so we need + * only recurse into any sub-nodes it has. * - * We assume that the walker is not interested in List nodes per se, - * so when we expect a List we just recurse directly to self without + * We assume that the walker is not interested in List nodes per se, so + * when we expect a List we just recurse directly to self without * bothering to call the walker. */ if (node == NULL) @@ -1478,7 +1512,7 @@ expression_tree_walker(Node *node, bool (*walker) (), void *context) break; case T_Expr: { - Expr *expr = (Expr *) node; + Expr *expr = (Expr *) node; if (expr->opType == SUBPLAN_EXPR) { @@ -1500,6 +1534,7 @@ expression_tree_walker(Node *node, bool (*walker) (), void *context) case T_ArrayRef: { ArrayRef *aref = (ArrayRef *) node; + /* recurse directly for upper/lower array index lists */ if (expression_tree_walker((Node *) aref->refupperindexpr, walker, context)) @@ -1519,10 +1554,12 @@ expression_tree_walker(Node *node, bool (*walker) (), void *context) case T_CaseExpr: { CaseExpr *caseexpr = (CaseExpr *) node; + /* we assume walker doesn't care about CaseWhens, either */ foreach(temp, caseexpr->args) { CaseWhen *when = (CaseWhen *) lfirst(temp); + Assert(IsA(when, CaseWhen)); if (walker(when->expr, context)) return true; @@ -1538,12 +1575,14 @@ expression_tree_walker(Node *node, bool (*walker) (), void *context) break; case T_SubLink: { - SubLink *sublink = (SubLink *) node; + SubLink *sublink = (SubLink *) node; - /* If the SubLink has already been processed by subselect.c, - * it will have lefthand=NIL, and we only need to look at - * the oper list. Otherwise we only need to look at lefthand - * (the Oper nodes in the oper list are deemed uninteresting). + /* + * If the SubLink has already been processed by + * subselect.c, it will have lefthand=NIL, and we only + * need to look at the oper list. Otherwise we only need + * to look at lefthand (the Oper nodes in the oper list + * are deemed uninteresting). */ if (sublink->lefthand) return walker((Node *) sublink->lefthand, context); @@ -1628,18 +1667,19 @@ expression_tree_walker(Node *node, bool (*walker) (), void *context) */ Node * -expression_tree_mutator(Node *node, Node * (*mutator) (), void *context) + expression_tree_mutator(Node *node, Node *(*mutator) (), void *context) { + /* - * The mutator has already decided not to modify the current node, - * but we must call the mutator for any sub-nodes. + * The mutator has already decided not to modify the current node, but + * we must call the mutator for any sub-nodes. */ #define FLATCOPY(newnode, node, nodetype) \ ( (newnode) = makeNode(nodetype), \ memcpy((newnode), (node), sizeof(nodetype)) ) -#define CHECKFLATCOPY(newnode, node, nodetype) \ +#define CHECKFLATCOPY(newnode, node, nodetype) \ ( AssertMacro(IsA((node), nodetype)), \ (newnode) = makeNode(nodetype), \ memcpy((newnode), (node), sizeof(nodetype)) ) @@ -1659,31 +1699,41 @@ expression_tree_mutator(Node *node, Node * (*mutator) (), void *context) return (Node *) copyObject(node); case T_Expr: { - Expr *expr = (Expr *) node; - Expr *newnode; + Expr *expr = (Expr *) node; + Expr *newnode; FLATCOPY(newnode, expr, Expr); if (expr->opType == SUBPLAN_EXPR) { - SubLink *oldsublink = ((SubPlan *) expr->oper)->sublink; - SubPlan *newsubplan; + SubLink *oldsublink = ((SubPlan *) expr->oper)->sublink; + SubPlan *newsubplan; /* flat-copy the oper node, which is a SubPlan */ CHECKFLATCOPY(newsubplan, expr->oper, SubPlan); newnode->oper = (Node *) newsubplan; /* likewise its SubLink node */ CHECKFLATCOPY(newsubplan->sublink, oldsublink, SubLink); - /* transform args list (params to be passed to subplan) */ + + /* + * transform args list (params to be passed to + * subplan) + */ MUTATE(newnode->args, expr->args, List *); /* transform sublink's oper list as well */ - MUTATE(newsubplan->sublink->oper, oldsublink->oper, List*); - /* but not the subplan itself, which is referenced as-is */ + MUTATE(newsubplan->sublink->oper, oldsublink->oper, List *); + + /* + * but not the subplan itself, which is referenced + * as-is + */ } else { - /* for other Expr node types, just transform args list, - * linking to original oper node (OK?) + + /* + * for other Expr node types, just transform args + * list, linking to original oper node (OK?) */ MUTATE(newnode->args, expr->args, List *); } @@ -1692,8 +1742,8 @@ expression_tree_mutator(Node *node, Node * (*mutator) (), void *context) break; case T_Aggref: { - Aggref *aggref = (Aggref *) node; - Aggref *newnode; + Aggref *aggref = (Aggref *) node; + Aggref *newnode; FLATCOPY(newnode, aggref, Aggref); MUTATE(newnode->target, aggref->target, Node *); @@ -1702,8 +1752,8 @@ expression_tree_mutator(Node *node, Node * (*mutator) (), void *context) break; case T_Iter: { - Iter *iter = (Iter *) node; - Iter *newnode; + Iter *iter = (Iter *) node; + Iter *newnode; FLATCOPY(newnode, iter, Iter); MUTATE(newnode->iterexpr, iter->iterexpr, Node *); @@ -1763,12 +1813,14 @@ expression_tree_mutator(Node *node, Node * (*mutator) (), void *context) break; case T_SubLink: { - /* A "bare" SubLink (note we will not come here if we found - * a SUBPLAN_EXPR node above it). Transform the lefthand side, - * but not the oper list nor the subquery. + + /* + * A "bare" SubLink (note we will not come here if we + * found a SUBPLAN_EXPR node above it). Transform the + * lefthand side, but not the oper list nor the subquery. */ - SubLink *sublink = (SubLink *) node; - SubLink *newnode; + SubLink *sublink = (SubLink *) node; + SubLink *newnode; FLATCOPY(newnode, sublink, SubLink); MUTATE(newnode->lefthand, sublink->lefthand, List *); @@ -1777,9 +1829,12 @@ expression_tree_mutator(Node *node, Node * (*mutator) (), void *context) break; case T_List: { - /* We assume the mutator isn't interested in the list nodes - * per se, so just invoke it on each list element. - * NOTE: this would fail badly on a list with integer elements! + + /* + * We assume the mutator isn't interested in the list + * nodes per se, so just invoke it on each list element. + * NOTE: this would fail badly on a list with integer + * elements! */ List *resultlist = NIL; List *temp; @@ -1795,9 +1850,13 @@ expression_tree_mutator(Node *node, Node * (*mutator) (), void *context) break; case T_TargetEntry: { - /* We mutate the expression, but not the resdom, by default. */ - TargetEntry *targetentry = (TargetEntry *) node; - TargetEntry *newnode; + + /* + * We mutate the expression, but not the resdom, by + * default. + */ + TargetEntry *targetentry = (TargetEntry *) node; + TargetEntry *newnode; FLATCOPY(newnode, targetentry, TargetEntry); MUTATE(newnode->expr, targetentry->expr, Node *); diff --git a/src/backend/optimizer/util/pathnode.c b/src/backend/optimizer/util/pathnode.c index 400c813125c..69a28138d8a 100644 --- a/src/backend/optimizer/util/pathnode.c +++ b/src/backend/optimizer/util/pathnode.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/util/pathnode.c,v 1.62 2000/03/22 22:08:35 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/util/pathnode.c,v 1.63 2000/04/12 17:15:24 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -42,6 +42,7 @@ compare_path_costs(Path *path1, Path *path2, CostSelector criterion) return -1; if (path1->startup_cost > path2->startup_cost) return +1; + /* * If paths have the same startup cost (not at all unlikely), * order them by total cost. @@ -57,6 +58,7 @@ compare_path_costs(Path *path1, Path *path2, CostSelector criterion) return -1; if (path1->total_cost > path2->total_cost) return +1; + /* * If paths have the same total cost, order them by startup cost. */ @@ -172,7 +174,8 @@ set_cheapest(RelOptInfo *parent_rel) void add_path(RelOptInfo *parent_rel, Path *new_path) { - bool accept_new = true; /* unless we find a superior old path */ + bool accept_new = true; /* unless we find a superior old + * path */ List *p1_prev = NIL; List *p1; @@ -184,36 +187,39 @@ add_path(RelOptInfo *parent_rel, Path *new_path) foreach(p1, parent_rel->pathlist) { Path *old_path = (Path *) lfirst(p1); - bool remove_old = false; /* unless new proves superior */ + bool remove_old = false; /* unless new proves superior */ int costcmp; costcmp = compare_path_costs(new_path, old_path, TOTAL_COST); + /* - * If the two paths compare differently for startup and total cost, - * then we want to keep both, and we can skip the (much slower) - * comparison of pathkeys. If they compare the same, proceed with - * the pathkeys comparison. Note this test relies on the fact that - * compare_path_costs will only return 0 if both costs are equal - * (and, therefore, there's no need to call it twice in that case). + * If the two paths compare differently for startup and total + * cost, then we want to keep both, and we can skip the (much + * slower) comparison of pathkeys. If they compare the same, + * proceed with the pathkeys comparison. Note this test relies on + * the fact that compare_path_costs will only return 0 if both + * costs are equal (and, therefore, there's no need to call it + * twice in that case). */ if (costcmp == 0 || - costcmp == compare_path_costs(new_path, old_path, STARTUP_COST)) + costcmp == compare_path_costs(new_path, old_path, STARTUP_COST)) { switch (compare_pathkeys(new_path->pathkeys, old_path->pathkeys)) { case PATHKEYS_EQUAL: if (costcmp < 0) - remove_old = true; /* new dominates old */ + remove_old = true; /* new dominates old */ else - accept_new = false; /* old equals or dominates new */ + accept_new = false; /* old equals or dominates + * new */ break; case PATHKEYS_BETTER1: if (costcmp <= 0) - remove_old = true; /* new dominates old */ + remove_old = true; /* new dominates old */ break; case PATHKEYS_BETTER2: if (costcmp >= 0) - accept_new = false; /* old dominates new */ + accept_new = false; /* old dominates new */ break; case PATHKEYS_DIFFERENT: /* keep both paths, since they have different ordering */ @@ -241,7 +247,7 @@ add_path(RelOptInfo *parent_rel, Path *new_path) * scanning the pathlist; we will not add new_path, and we assume * new_path cannot dominate any other elements of the pathlist. */ - if (! accept_new) + if (!accept_new) break; } @@ -315,12 +321,14 @@ create_index_path(Query *root, if (pathnode->path.pathkeys == NIL) { /* No ordering available from index, is that OK? */ - if (! ScanDirectionIsNoMovement(indexscandir)) + if (!ScanDirectionIsNoMovement(indexscandir)) elog(ERROR, "create_index_path: failed to create ordered index scan"); } else { - /* The index is ordered, and build_index_pathkeys defaulted to + + /* + * The index is ordered, and build_index_pathkeys defaulted to * forward scan, so make sure we mark the pathnode properly. */ if (ScanDirectionIsNoMovement(indexscandir)) @@ -341,11 +349,11 @@ create_index_path(Query *root, pathnode->indexscandir = indexscandir; /* - * This routine is only used to generate "standalone" indexpaths, - * not nestloop inner indexpaths. So joinrelids is always NIL - * and the number of rows is the same as the parent rel's estimate. + * This routine is only used to generate "standalone" indexpaths, not + * nestloop inner indexpaths. So joinrelids is always NIL and the + * number of rows is the same as the parent rel's estimate. */ - pathnode->joinrelids = NIL; /* no join clauses here */ + pathnode->joinrelids = NIL; /* no join clauses here */ pathnode->rows = rel->rows; cost_index(&pathnode->path, root, rel, index, indexquals, false); @@ -359,20 +367,23 @@ create_index_path(Query *root, * pathnode. * */ -TidPath * +TidPath * create_tidscan_path(RelOptInfo *rel, List *tideval) { - TidPath *pathnode = makeNode(TidPath); + TidPath *pathnode = makeNode(TidPath); pathnode->path.pathtype = T_TidScan; pathnode->path.parent = rel; pathnode->path.pathkeys = NIL; - pathnode->tideval = copyObject(tideval); /* is copy really necessary? */ + pathnode->tideval = copyObject(tideval); /* is copy really + * necessary? */ pathnode->unjoined_relids = NIL; cost_tidscan(&pathnode->path, rel, tideval); - /* divide selectivity for each clause to get an equal selectivity - * as IndexScan does OK ? + + /* + * divide selectivity for each clause to get an equal selectivity as + * IndexScan does OK ? */ return pathnode; @@ -485,7 +496,7 @@ create_mergejoin_path(RelOptInfo *joinrel, * 'innerdisbursion' is an estimate of the disbursion of the inner hash key * */ -HashPath * +HashPath * create_hashjoin_path(RelOptInfo *joinrel, Path *outer_path, Path *inner_path, diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index 716c31ab0f1..e9d7690e00c 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/util/plancat.c,v 1.49 2000/02/18 09:30:09 inoue Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/util/plancat.c,v 1.50 2000/04/12 17:15:24 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -50,7 +50,7 @@ relation_info(Query *root, Index relid, Form_pg_class relation; relationTuple = SearchSysCacheTuple(RELOID, - ObjectIdGetDatum(relationObjectId), + ObjectIdGetDatum(relationObjectId), 0, 0, 0); if (!HeapTupleIsValid(relationTuple)) elog(ERROR, "relation_info: Relation %u not found", @@ -81,7 +81,7 @@ find_secondary_indexes(Query *root, Index relid) Oid indrelid = getrelid(relid, root->rtable); Relation relation; HeapScanDesc scan; - ScanKeyData indexKey; + ScanKeyData indexKey; HeapTuple indexTuple; /* Scan pg_index for tuples describing indexes of this rel */ @@ -97,27 +97,28 @@ find_secondary_indexes(Query *root, Index relid) while (HeapTupleIsValid(indexTuple = heap_getnext(scan, 0))) { - Form_pg_index index = (Form_pg_index) GETSTRUCT(indexTuple); - IndexOptInfo *info = makeNode(IndexOptInfo); - int i; - Relation indexRelation; - Oid relam; - uint16 amorderstrategy; + Form_pg_index index = (Form_pg_index) GETSTRUCT(indexTuple); + IndexOptInfo *info = makeNode(IndexOptInfo); + int i; + Relation indexRelation; + Oid relam; + uint16 amorderstrategy; /* * Need to make these arrays large enough to be sure there is a * terminating 0 at the end of each one. */ - info->classlist = (Oid *) palloc(sizeof(Oid) * (INDEX_MAX_KEYS+1)); - info->indexkeys = (int *) palloc(sizeof(int) * (INDEX_MAX_KEYS+1)); - info->ordering = (Oid *) palloc(sizeof(Oid) * (INDEX_MAX_KEYS+1)); + info->classlist = (Oid *) palloc(sizeof(Oid) * (INDEX_MAX_KEYS + 1)); + info->indexkeys = (int *) palloc(sizeof(int) * (INDEX_MAX_KEYS + 1)); + info->ordering = (Oid *) palloc(sizeof(Oid) * (INDEX_MAX_KEYS + 1)); /* Extract info from the pg_index tuple */ info->indexoid = index->indexrelid; - info->indproc = index->indproc; /* functional index ?? */ - if (VARSIZE(&index->indpred) != 0) /* partial index ?? */ + info->indproc = index->indproc; /* functional index ?? */ + if (VARSIZE(&index->indpred) != 0) /* partial index ?? */ { char *predString = fmgr(F_TEXTOUT, &index->indpred); + info->indpred = (List *) stringToNode(predString); pfree(predString); } @@ -143,26 +144,25 @@ find_secondary_indexes(Query *root, Index relid) index_close(indexRelation); /* - * Fetch the ordering operators associated with the index, - * if any. + * Fetch the ordering operators associated with the index, if any. */ - MemSet(info->ordering, 0, sizeof(Oid) * (INDEX_MAX_KEYS+1)); + MemSet(info->ordering, 0, sizeof(Oid) * (INDEX_MAX_KEYS + 1)); if (amorderstrategy != 0) { for (i = 0; i < INDEX_MAX_KEYS && index->indclass[i]; i++) { - HeapTuple amopTuple; - Form_pg_amop amop; + HeapTuple amopTuple; + Form_pg_amop amop; amopTuple = SearchSysCacheTuple(AMOPSTRATEGY, ObjectIdGetDatum(relam), - ObjectIdGetDatum(index->indclass[i]), + ObjectIdGetDatum(index->indclass[i]), UInt16GetDatum(amorderstrategy), 0); if (!HeapTupleIsValid(amopTuple)) elog(ERROR, "find_secondary_indexes: no amop %u %u %d", - relam, index->indclass[i], (int) amorderstrategy); + relam, index->indclass[i], (int) amorderstrategy); amop = (Form_pg_amop) GETSTRUCT(amopTuple); info->ordering[i] = amop->amopopr; } diff --git a/src/backend/optimizer/util/relnode.c b/src/backend/optimizer/util/relnode.c index 694a1b905e1..da7059ce915 100644 --- a/src/backend/optimizer/util/relnode.c +++ b/src/backend/optimizer/util/relnode.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/util/relnode.c,v 1.25 2000/02/18 23:47:31 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/util/relnode.c,v 1.26 2000/04/12 17:15:24 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -24,15 +24,15 @@ static List *new_join_tlist(List *tlist, int first_resdomno); static List *build_joinrel_restrictlist(RelOptInfo *joinrel, - RelOptInfo *outer_rel, - RelOptInfo *inner_rel); + RelOptInfo *outer_rel, + RelOptInfo *inner_rel); static void build_joinrel_joinlist(RelOptInfo *joinrel, - RelOptInfo *outer_rel, - RelOptInfo *inner_rel); + RelOptInfo *outer_rel, + RelOptInfo *inner_rel); static List *subbuild_joinrel_restrictlist(RelOptInfo *joinrel, - List *joininfo_list); + List *joininfo_list); static void subbuild_joinrel_joinlist(RelOptInfo *joinrel, - List *joininfo_list); + List *joininfo_list); /* @@ -50,7 +50,10 @@ get_base_rel(Query *root, int relid) { rel = (RelOptInfo *) lfirst(baserels); - /* We know length(rel->relids) == 1 for all members of base_rel_list */ + /* + * We know length(rel->relids) == 1 for all members of + * base_rel_list + */ if (lfirsti(rel->relids) == relid) return rel; } @@ -75,18 +78,20 @@ get_base_rel(Query *root, int relid) if (relid < 0) { + /* - * If the relation is a materialized relation, assume - * constants for sizes. + * If the relation is a materialized relation, assume constants + * for sizes. */ rel->pages = _NONAME_RELATION_PAGES_; rel->tuples = _NONAME_RELATION_TUPLES_; } else { + /* - * Otherwise, retrieve relation statistics from the - * system catalogs. + * Otherwise, retrieve relation statistics from the system + * catalogs. */ relation_info(root, relid, &rel->indexed, &rel->pages, &rel->tuples); @@ -162,6 +167,7 @@ get_join_rel(Query *root, if (joinrel) { + /* * Yes, so we only need to figure the restrictlist for this * particular pair of component relations. @@ -198,13 +204,13 @@ get_join_rel(Query *root, * of the outer and inner join relations and then merging the results * together. * - * NOTE: the tlist order for a join rel will depend on which pair - * of outer and inner rels we first try to build it from. But the + * NOTE: the tlist order for a join rel will depend on which pair of + * outer and inner rels we first try to build it from. But the * contents should be the same regardless. * - * XXX someday: consider pruning vars from the join's targetlist - * if they are needed only to evaluate restriction clauses of this - * join, and will never be accessed at higher levels of the plantree. + * XXX someday: consider pruning vars from the join's targetlist if they + * are needed only to evaluate restriction clauses of this join, and + * will never be accessed at higher levels of the plantree. */ new_outer_tlist = new_join_tlist(outer_rel->targetlist, 1); new_inner_tlist = new_join_tlist(inner_rel->targetlist, @@ -212,9 +218,9 @@ get_join_rel(Query *root, joinrel->targetlist = nconc(new_outer_tlist, new_inner_tlist); /* - * Construct restrict and join clause lists for the new joinrel. - * (The caller might or might not need the restrictlist, but - * I need it anyway for set_joinrel_size_estimates().) + * Construct restrict and join clause lists for the new joinrel. (The + * caller might or might not need the restrictlist, but I need it + * anyway for set_joinrel_size_estimates().) */ restrictlist = build_joinrel_restrictlist(joinrel, outer_rel, inner_rel); if (restrictlist_ptr) @@ -246,7 +252,7 @@ get_join_rel(Query *root, * * XXX the above comment refers to code that is long dead and gone; * we don't keep track of joinlists for individual targetlist entries - * anymore. For now, all vars present in either input tlist will be + * anymore. For now, all vars present in either input tlist will be * emitted in the join's tlist. * * 'tlist' is the target list of one of the join relations @@ -286,16 +292,16 @@ new_join_tlist(List *tlist, * the join lists need only be computed once for any join RelOptInfo. * The join lists are fully determined by the set of rels making up the * joinrel, so we should get the same results (up to ordering) from any - * candidate pair of sub-relations. But the restriction list is whatever + * candidate pair of sub-relations. But the restriction list is whatever * is not handled in the sub-relations, so it depends on which * sub-relations are considered. * * If a join clause from an input relation refers to base rels still not * present in the joinrel, then it is still a join clause for the joinrel; - * we put it into an appropriate JoinInfo list for the joinrel. Otherwise, + * we put it into an appropriate JoinInfo list for the joinrel. Otherwise, * the clause is now a restrict clause for the joined relation, and we * return it to the caller of build_joinrel_restrictlist() to be stored in - * join paths made from this pair of sub-relations. (It will not need to + * join paths made from this pair of sub-relations. (It will not need to * be considered further up the join tree.) * * 'joinrel' is a join relation node @@ -304,11 +310,11 @@ new_join_tlist(List *tlist, * * build_joinrel_restrictlist() returns a list of relevant restrictinfos, * whereas build_joinrel_joinlist() stores its results in the joinrel's - * joininfo lists. One or the other must accept each given clause! + * joininfo lists. One or the other must accept each given clause! * * NB: Formerly, we made deep(!) copies of each input RestrictInfo to pass * up to the join relation. I believe this is no longer necessary, because - * RestrictInfo nodes are no longer context-dependent. Instead, just include + * RestrictInfo nodes are no longer context-dependent. Instead, just include * the original nodes in the lists made for the join relation. */ static List * @@ -316,9 +322,10 @@ build_joinrel_restrictlist(RelOptInfo *joinrel, RelOptInfo *outer_rel, RelOptInfo *inner_rel) { + /* - * We must eliminate duplicates, since we will see the - * same clauses arriving from both input relations... + * We must eliminate duplicates, since we will see the same clauses + * arriving from both input relations... */ return LispUnion(subbuild_joinrel_restrictlist(joinrel, outer_rel->joininfo), @@ -348,6 +355,7 @@ subbuild_joinrel_restrictlist(RelOptInfo *joinrel, if (is_subseti(joininfo->unjoined_relids, joinrel->relids)) { + /* * Clauses in this JoinInfo list become restriction clauses * for the joinrel, since they refer to no outside rels. @@ -360,9 +368,10 @@ subbuild_joinrel_restrictlist(RelOptInfo *joinrel, } else { + /* - * These clauses are still join clauses at this level, - * so we ignore them in this routine. + * These clauses are still join clauses at this level, so we + * ignore them in this routine. */ } } @@ -385,18 +394,20 @@ subbuild_joinrel_joinlist(RelOptInfo *joinrel, joinrel->relids); if (new_unjoined_relids == NIL) { + /* * Clauses in this JoinInfo list become restriction clauses - * for the joinrel, since they refer to no outside rels. - * So we can ignore them in this routine. + * for the joinrel, since they refer to no outside rels. So we + * can ignore them in this routine. */ } else { + /* - * These clauses are still join clauses at this level, - * so find or make the appropriate JoinInfo item for the joinrel, - * and add the clauses to it (eliminating duplicates). + * These clauses are still join clauses at this level, so find + * or make the appropriate JoinInfo item for the joinrel, and + * add the clauses to it (eliminating duplicates). */ JoinInfo *new_joininfo; diff --git a/src/backend/optimizer/util/tlist.c b/src/backend/optimizer/util/tlist.c index b4c745b25f3..d4094dac12a 100644 --- a/src/backend/optimizer/util/tlist.c +++ b/src/backend/optimizer/util/tlist.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/util/tlist.c,v 1.43 2000/01/27 18:11:34 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/util/tlist.c,v 1.44 2000/04/12 17:15:24 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -27,7 +27,7 @@ /* * tlistentry_member * Finds the (first) member of the given tlist whose expression is - * equal() to the given expression. Result is NULL if no such member. + * equal() to the given expression. Result is NULL if no such member. */ TargetEntry * tlistentry_member(Node *node, List *targetlist) @@ -36,7 +36,7 @@ tlistentry_member(Node *node, List *targetlist) foreach(temp, targetlist) { - TargetEntry *tlentry = (TargetEntry *) lfirst(temp); + TargetEntry *tlentry = (TargetEntry *) lfirst(temp); if (equal(node, tlentry->expr)) return tlentry; @@ -87,12 +87,12 @@ tlist_member(Node *node, List *targetlist) void add_var_to_tlist(RelOptInfo *rel, Var *var) { - if (! tlistentry_member((Node *) var, rel->targetlist)) + if (!tlistentry_member((Node *) var, rel->targetlist)) { /* XXX is copyObject necessary here? */ rel->targetlist = lappend(rel->targetlist, - create_tl_element((Var *) copyObject(var), - length(rel->targetlist) + 1)); + create_tl_element((Var *) copyObject(var), + length(rel->targetlist) + 1)); } } @@ -189,7 +189,7 @@ add_to_flat_tlist(List *tlist, List *vars) { Var *var = lfirst(v); - if (! tlistentry_member((Node *) var, tlist)) + if (!tlistentry_member((Node *) var, tlist)) { Resdom *r; diff --git a/src/backend/optimizer/util/var.c b/src/backend/optimizer/util/var.c index f438845cff9..bed7be7f08a 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.25 2000/01/26 05:56:40 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/util/var.c,v 1.26 2000/04/12 17:15:24 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -20,7 +20,8 @@ #include "optimizer/var.h" -typedef struct { +typedef struct +{ List *varlist; bool includeUpperVars; } pull_var_clause_context; @@ -28,7 +29,7 @@ typedef struct { static bool pull_varnos_walker(Node *node, List **listptr); static bool contain_var_clause_walker(Node *node, void *context); static bool pull_var_clause_walker(Node *node, - pull_var_clause_context *context); + pull_var_clause_context *context); /* @@ -54,7 +55,8 @@ pull_varnos_walker(Node *node, List **listptr) return false; if (IsA(node, Var)) { - Var *var = (Var *) node; + Var *var = (Var *) node; + if (var->varlevelsup == 0 && !intMember(var->varno, *listptr)) *listptr = lconsi(var->varno, *listptr); return false; @@ -83,7 +85,8 @@ contain_var_clause_walker(Node *node, void *context) if (IsA(node, Var)) { if (((Var *) node)->varlevelsup == 0) - return true; /* abort the tree traversal and return true */ + return true; /* abort the tree traversal and return + * true */ return false; } return expression_tree_walker(node, contain_var_clause_walker, context); @@ -94,7 +97,7 @@ contain_var_clause_walker(Node *node, void *context) * Recursively pulls all var nodes from an expression clause. * * Upper-level vars (with varlevelsup > 0) are included only - * if includeUpperVars is true. Most callers probably want + * if includeUpperVars is true. Most callers probably want * to ignore upper-level vars. * * Returns list of varnodes found. Note the varnodes themselves are not @@ -103,7 +106,7 @@ contain_var_clause_walker(Node *node, void *context) List * pull_var_clause(Node *clause, bool includeUpperVars) { - pull_var_clause_context context; + pull_var_clause_context context; context.varlist = NIL; context.includeUpperVars = includeUpperVars; |