clauses.c
来自「PostgreSQL7.4.6 for Linux」· C语言 代码 · 共 2,256 行 · 第 1/5 页
C
2,256 行
/* else fall through to check args */ } if (IsA(node, OpExpr)) { OpExpr *expr = (OpExpr *) node; if (expr->opretset) return true; /* else fall through to check args */ } /* Avoid recursion for some cases that can't return a set */ if (IsA(node, Aggref)) return false; if (IsA(node, DistinctExpr)) return false; if (IsA(node, ScalarArrayOpExpr)) return false; if (IsA(node, BoolExpr)) return false; if (IsA(node, SubLink)) return false; if (IsA(node, SubPlan)) return false; if (IsA(node, ArrayExpr)) return false; if (IsA(node, CoalesceExpr)) return false; if (IsA(node, NullIfExpr)) return false; return expression_tree_walker(node, expression_returns_set_walker, context);}/***************************************************************************** * Subplan clause manipulation *****************************************************************************//* * contain_subplans * Recursively search for subplan nodes within a clause. * * If we see a SubLink node, we will return TRUE. This is only possible if * the expression tree hasn't yet been transformed by subselect.c. We do not * know whether the node will produce a true subplan or just an initplan, * but we make the conservative assumption that it will be a subplan. * * Returns true if any subplan found. */boolcontain_subplans(Node *clause){ return contain_subplans_walker(clause, NULL);}static boolcontain_subplans_walker(Node *node, void *context){ if (node == NULL) return false; if (IsA(node, SubPlan) || IsA(node, SubLink)) return true; /* abort the tree traversal and return * true */ return expression_tree_walker(node, contain_subplans_walker, context);}/***************************************************************************** * Check clauses for mutable functions *****************************************************************************//* * contain_mutable_functions * Recursively search for mutable functions within a clause. * * Returns true if any mutable function (or operator implemented by a * mutable function) is found. This test is needed so that we don't * mistakenly think that something like "WHERE random() < 0.5" can be treated * as a constant qualification. * * XXX we do not examine sub-selects to see if they contain uses of * mutable functions. It's not real clear if that is correct or not... */boolcontain_mutable_functions(Node *clause){ return contain_mutable_functions_walker(clause, NULL);}static boolcontain_mutable_functions_walker(Node *node, void *context){ if (node == NULL) return false; if (IsA(node, FuncExpr)) { FuncExpr *expr = (FuncExpr *) node; if (func_volatile(expr->funcid) != PROVOLATILE_IMMUTABLE) return true; /* else fall through to check args */ } if (IsA(node, OpExpr)) { OpExpr *expr = (OpExpr *) node; if (op_volatile(expr->opno) != PROVOLATILE_IMMUTABLE) return true; /* else fall through to check args */ } if (IsA(node, DistinctExpr)) { DistinctExpr *expr = (DistinctExpr *) node; if (op_volatile(expr->opno) != PROVOLATILE_IMMUTABLE) return true; /* else fall through to check args */ } if (IsA(node, ScalarArrayOpExpr)) { ScalarArrayOpExpr *expr = (ScalarArrayOpExpr *) node; if (op_volatile(expr->opno) != PROVOLATILE_IMMUTABLE) return true; /* else fall through to check args */ } if (IsA(node, NullIfExpr)) { NullIfExpr *expr = (NullIfExpr *) node; if (op_volatile(expr->opno) != PROVOLATILE_IMMUTABLE) return true; /* else fall through to check args */ } if (IsA(node, SubLink)) { SubLink *sublink = (SubLink *) node; List *opid; foreach(opid, sublink->operOids) { if (op_volatile(lfirsto(opid)) != PROVOLATILE_IMMUTABLE) return true; } /* else fall through to check args */ } return expression_tree_walker(node, contain_mutable_functions_walker, context);}/***************************************************************************** * Check clauses for volatile functions *****************************************************************************//* * contain_volatile_functions * Recursively search for volatile functions within a clause. * * Returns true if any volatile function (or operator implemented by a * volatile function) is found. This test prevents invalid conversions * of volatile expressions into indexscan quals. * * XXX we do not examine sub-selects to see if they contain uses of * volatile functions. It's not real clear if that is correct or not... */boolcontain_volatile_functions(Node *clause){ return contain_volatile_functions_walker(clause, NULL);}static boolcontain_volatile_functions_walker(Node *node, void *context){ if (node == NULL) return false; if (IsA(node, FuncExpr)) { FuncExpr *expr = (FuncExpr *) node; if (func_volatile(expr->funcid) == PROVOLATILE_VOLATILE) return true; /* else fall through to check args */ } if (IsA(node, OpExpr)) { OpExpr *expr = (OpExpr *) node; if (op_volatile(expr->opno) == PROVOLATILE_VOLATILE) return true; /* else fall through to check args */ } if (IsA(node, DistinctExpr)) { DistinctExpr *expr = (DistinctExpr *) node; if (op_volatile(expr->opno) == PROVOLATILE_VOLATILE) return true; /* else fall through to check args */ } if (IsA(node, ScalarArrayOpExpr)) { ScalarArrayOpExpr *expr = (ScalarArrayOpExpr *) node; if (op_volatile(expr->opno) == PROVOLATILE_VOLATILE) return true; /* else fall through to check args */ } if (IsA(node, NullIfExpr)) { NullIfExpr *expr = (NullIfExpr *) node; if (op_volatile(expr->opno) == PROVOLATILE_VOLATILE) return true; /* else fall through to check args */ } if (IsA(node, SubLink)) { SubLink *sublink = (SubLink *) node; List *opid; foreach(opid, sublink->operOids) { if (op_volatile(lfirsto(opid)) == PROVOLATILE_VOLATILE) return true; } /* else fall through to check args */ } return expression_tree_walker(node, contain_volatile_functions_walker, context);}/***************************************************************************** * Check clauses for nonstrict functions *****************************************************************************//* * contain_nonstrict_functions * Recursively search for nonstrict functions within a clause. * * Returns true if any nonstrict construct is found --- ie, anything that * could produce non-NULL output with a NULL input. * * XXX we do not examine sub-selects to see if they contain uses of * nonstrict functions. It's not real clear if that is correct or not... * for the current usage it does not matter, since inline_function() * rejects cases with sublinks. */boolcontain_nonstrict_functions(Node *clause){ return contain_nonstrict_functions_walker(clause, NULL);}static boolcontain_nonstrict_functions_walker(Node *node, void *context){ if (node == NULL) return false; if (IsA(node, FuncExpr)) { FuncExpr *expr = (FuncExpr *) node; if (!func_strict(expr->funcid)) return true; /* else fall through to check args */ } if (IsA(node, OpExpr)) { OpExpr *expr = (OpExpr *) node; if (!op_strict(expr->opno)) return true; /* else fall through to check args */ } if (IsA(node, DistinctExpr)) { /* IS DISTINCT FROM is inherently non-strict */ return true; } if (IsA(node, ScalarArrayOpExpr)) { /* inherently non-strict, consider null scalar and empty array */ return true; } if (IsA(node, BoolExpr)) { BoolExpr *expr = (BoolExpr *) node; switch (expr->boolop) { case OR_EXPR: case AND_EXPR: /* OR, AND are inherently non-strict */ return true; default: break; } } if (IsA(node, CaseExpr)) return true; /* NB: ArrayExpr might someday be nonstrict */ if (IsA(node, CoalesceExpr)) return true; if (IsA(node, NullIfExpr)) return true; if (IsA(node, NullTest)) return true; if (IsA(node, BooleanTest)) return true; if (IsA(node, SubLink)) { SubLink *sublink = (SubLink *) node; List *opid; foreach(opid, sublink->operOids) { if (!op_strict(lfirsto(opid))) return true; } /* else fall through to check args */ } return expression_tree_walker(node, contain_nonstrict_functions_walker, context);}/***************************************************************************** * Check for "pseudo-constant" clauses *****************************************************************************//* * is_pseudo_constant_clause * Detect whether a clause is "constant", ie, it contains no variables * of the current query level and no uses of volatile functions. * Such a clause is not necessarily a true constant: it can still contain * Params and outer-level Vars, not to mention functions whose results * may vary from one statement to the next. However, the clause's value * will be constant over any one scan of the current query, so it can be * used as an indexscan key or (if a top-level qual) can be pushed up to * become a gating qual. */boolis_pseudo_constant_clause(Node *clause){ /* * We could implement this check in one recursive scan. But since the * check for volatile functions is both moderately expensive and * unlikely to fail, it seems better to look for Vars first and only * check for volatile functions if we find no Vars. */ if (!contain_var_clause(clause) && !contain_volatile_functions(clause)) return true; return false;}/* * pull_constant_clauses * Scan through a list of qualifications and separate "constant" quals * from those that are not. * * Returns a list of the pseudo-constant clauses in constantQual and the * remaining quals as the return value. */List *pull_constant_clauses(List *quals, List **constantQual){ FastList constqual, restqual; List *q; FastListInit(&constqual); FastListInit(&restqual); foreach(q, quals) { Node *qual = (Node *) lfirst(q); if (is_pseudo_constant_clause(qual)) FastAppend(&constqual, qual); else FastAppend(&restqual, qual); } *constantQual = FastListValue(&constqual); return FastListValue(&restqual);}/***************************************************************************** * Tests on clauses of queries * * Possibly this code should go someplace else, since this isn't quite the * same meaning of "clause" as is used elsewhere in this module. But I can't * think of a better place for it... *****************************************************************************//* * Test whether a query uses DISTINCT ON, ie, has a distinct-list that is * not the same as the set of output columns. */boolhas_distinct_on_clause(Query *query){ List *targetList; /* Is there a DISTINCT clause at all? */ if (query->distinctClause == NIL) return false; /* * If the DISTINCT list contains all the nonjunk targetlist items, and * nothing else (ie, no junk tlist items), then it's a simple * DISTINCT, else it's DISTINCT ON. We do not require the lists to be * in the same order (since the parser may have adjusted the DISTINCT * clause ordering to agree with ORDER BY). Furthermore, a * non-DISTINCT junk tlist item that is in the sortClause is also * evidence of DISTINCT ON, since we don't allow ORDER BY on junk * tlist items when plain DISTINCT is used. * * This code assumes that the DISTINCT list is valid, ie, all its entries * match some entry of the tlist. */ foreach(targetList, query->targetList) { TargetEntry *tle = (TargetEntry *) lfirst(targetList); if (tle->resdom->ressortgroupref == 0) { if (tle->resdom->resjunk) continue; /* we can ignore unsorted junk cols */ return true; /* definitely not in DISTINCT list */ } if (targetIsInSortList(tle, query->distinctClause)) { if (tle->resdom->resjunk) return true; /* junk TLE in DISTINCT means DISTINCT ON */ /* else this TLE is okay, keep looking */ } else { /* This TLE is not in DISTINCT list */ if (!tle->resdom->resjunk) return true; /* non-junk, non-DISTINCT, so DISTINCT ON */ if (targetIsInSortList(tle, query->sortClause)) return true; /* sorted, non-distinct junk */ /* unsorted junk is okay, keep looking */ }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?