clauses.c
来自「postgresql8.3.4源码,开源数据库」· C语言 代码 · 共 2,294 行 · 第 1/5 页
C
2,294 行
* value itself, plus palloc overhead. */ if (!get_typbyval(aggtranstype)) { int32 aggtranstypmod; int32 avgwidth; /* * If transition state is of same type as first input, assume it's * the same typmod (same width) as well. This works for cases * like MAX/MIN and is probably somewhat reasonable otherwise. */ if (numArguments > 0 && aggtranstype == inputTypes[0]) aggtranstypmod = exprTypmod((Node *) linitial(aggref->args)); else aggtranstypmod = -1; avgwidth = get_typavgwidth(aggtranstype, aggtranstypmod); avgwidth = MAXALIGN(avgwidth); counts->transitionSpace += avgwidth + 2 * sizeof(void *); } /* * Complain if the aggregate's arguments contain any aggregates; * nested agg functions are semantically nonsensical. */ if (contain_agg_clause((Node *) aggref->args)) ereport(ERROR, (errcode(ERRCODE_GROUPING_ERROR), errmsg("aggregate function calls cannot be nested"))); /* * Having checked that, we need not recurse into the argument. */ return false; } Assert(!IsA(node, SubLink)); return expression_tree_walker(node, count_agg_clauses_walker, (void *) counts);}/***************************************************************************** * Support for expressions returning sets *****************************************************************************//* * expression_returns_set * Test whether an expression returns a set result. * * Because we use expression_tree_walker(), this can also be applied to * whole targetlists; it'll produce TRUE if any one of the tlist items * returns a set. */boolexpression_returns_set(Node *clause){ return expression_returns_set_walker(clause, NULL);}static boolexpression_returns_set_walker(Node *node, void *context){ if (node == NULL) return false; if (IsA(node, FuncExpr)) { FuncExpr *expr = (FuncExpr *) node; if (expr->funcretset) return true; /* 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, RowExpr)) return false; if (IsA(node, RowCompareExpr)) return false; if (IsA(node, CoalesceExpr)) return false; if (IsA(node, MinMaxExpr)) return false; if (IsA(node, XmlExpr)) return false; if (IsA(node, NullIfExpr)) return false; return expression_tree_walker(node, expression_returns_set_walker, context);}/* * expression_returns_set_rows * Estimate the number of rows in a set result. * * We use the product of the rowcount estimates of all the functions in * the given tree. The result is 1 if there are no set-returning functions. */doubleexpression_returns_set_rows(Node *clause){ double result = 1; (void) expression_returns_set_rows_walker(clause, &result); return result;}static boolexpression_returns_set_rows_walker(Node *node, double *count){ if (node == NULL) return false; if (IsA(node, FuncExpr)) { FuncExpr *expr = (FuncExpr *) node; if (expr->funcretset) *count *= get_func_rows(expr->funcid); } if (IsA(node, OpExpr)) { OpExpr *expr = (OpExpr *) node; if (expr->opretset) { set_opfuncid(expr); *count *= get_func_rows(expr->opfuncid); } } /* 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, RowExpr)) return false; if (IsA(node, RowCompareExpr)) return false; if (IsA(node, CoalesceExpr)) return false; if (IsA(node, MinMaxExpr)) return false; if (IsA(node, XmlExpr)) return false; if (IsA(node, NullIfExpr)) return false; return expression_tree_walker(node, expression_returns_set_rows_walker, (void *) count);}/***************************************************************************** * 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 */ } else if (IsA(node, OpExpr)) { OpExpr *expr = (OpExpr *) node; set_opfuncid(expr); if (func_volatile(expr->opfuncid) != PROVOLATILE_IMMUTABLE) return true; /* else fall through to check args */ } else if (IsA(node, DistinctExpr)) { DistinctExpr *expr = (DistinctExpr *) node; set_opfuncid((OpExpr *) expr); /* rely on struct equivalence */ if (func_volatile(expr->opfuncid) != PROVOLATILE_IMMUTABLE) return true; /* else fall through to check args */ } else if (IsA(node, ScalarArrayOpExpr)) { ScalarArrayOpExpr *expr = (ScalarArrayOpExpr *) node; set_sa_opfuncid(expr); if (func_volatile(expr->opfuncid) != PROVOLATILE_IMMUTABLE) return true; /* else fall through to check args */ } else if (IsA(node, CoerceViaIO)) { CoerceViaIO *expr = (CoerceViaIO *) node; Oid iofunc; Oid typioparam; bool typisvarlena; /* check the result type's input function */ getTypeInputInfo(expr->resulttype, &iofunc, &typioparam); if (func_volatile(iofunc) != PROVOLATILE_IMMUTABLE) return true; /* check the input type's output function */ getTypeOutputInfo(exprType((Node *) expr->arg), &iofunc, &typisvarlena); if (func_volatile(iofunc) != PROVOLATILE_IMMUTABLE) return true; /* else fall through to check args */ } else if (IsA(node, ArrayCoerceExpr)) { ArrayCoerceExpr *expr = (ArrayCoerceExpr *) node; if (OidIsValid(expr->elemfuncid) && func_volatile(expr->elemfuncid) != PROVOLATILE_IMMUTABLE) return true; /* else fall through to check args */ } else if (IsA(node, NullIfExpr)) { NullIfExpr *expr = (NullIfExpr *) node; set_opfuncid((OpExpr *) expr); /* rely on struct equivalence */ if (func_volatile(expr->opfuncid) != PROVOLATILE_IMMUTABLE) return true; /* else fall through to check args */ } else if (IsA(node, RowCompareExpr)) { RowCompareExpr *rcexpr = (RowCompareExpr *) node; ListCell *opid; foreach(opid, rcexpr->opnos) { if (op_volatile(lfirst_oid(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 */ } else if (IsA(node, OpExpr)) { OpExpr *expr = (OpExpr *) node; set_opfuncid(expr); if (func_volatile(expr->opfuncid) == PROVOLATILE_VOLATILE) return true; /* else fall through to check args */ } else if (IsA(node, DistinctExpr)) { DistinctExpr *expr = (DistinctExpr *) node; set_opfuncid((OpExpr *) expr); /* rely on struct equivalence */ if (func_volatile(expr->opfuncid) == PROVOLATILE_VOLATILE) return true; /* else fall through to check args */ } else if (IsA(node, ScalarArrayOpExpr)) { ScalarArrayOpExpr *expr = (ScalarArrayOpExpr *) node; set_sa_opfuncid(expr); if (func_volatile(expr->opfuncid) == PROVOLATILE_VOLATILE) return true; /* else fall through to check args */ } else if (IsA(node, CoerceViaIO)) { CoerceViaIO *expr = (CoerceViaIO *) node; Oid iofunc; Oid typioparam; bool typisvarlena; /* check the result type's input function */ getTypeInputInfo(expr->resulttype, &iofunc, &typioparam); if (func_volatile(iofunc) == PROVOLATILE_VOLATILE) return true; /* check the input type's output function */ getTypeOutputInfo(exprType((Node *) expr->arg), &iofunc, &typisvarlena); if (func_volatile(iofunc) == PROVOLATILE_VOLATILE) return true; /* else fall through to check args */ } else if (IsA(node, ArrayCoerceExpr)) { ArrayCoerceExpr *expr = (ArrayCoerceExpr *) node; if (OidIsValid(expr->elemfuncid) && func_volatile(expr->elemfuncid) == PROVOLATILE_VOLATILE) return true; /* else fall through to check args */ } else if (IsA(node, NullIfExpr)) { NullIfExpr *expr = (NullIfExpr *) node; set_opfuncid((OpExpr *) expr); /* rely on struct equivalence */ if (func_volatile(expr->opfuncid) == PROVOLATILE_VOLATILE) return true; /* else fall through to check args */ } else if (IsA(node, RowCompareExpr)) { /* RowCompare probably can't have volatile ops, but check anyway */ RowCompareExpr *rcexpr = (RowCompareExpr *) node; ListCell *opid; foreach(opid, rcexpr->opnos) { if (op_volatile(lfirst_oid(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.
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?