mirror of
https://github.com/postgres/postgres.git
synced 2025-11-06 07:49:08 +03:00
Add COST and ROWS options to CREATE/ALTER FUNCTION, plus underlying pg_proc
columns procost and prorows, to allow simple user adjustment of the estimated cost of a function call, as well as control of the estimated number of rows returned by a set-returning function. We might eventually wish to extend this to allow function-specific estimation routines, but there seems to be consensus that we should try a simple constant estimate first. In particular this provides a relatively simple way to control the order in which different WHERE clauses are applied in a plan node, which is a Good Thing in view of the fact that the recent EquivalenceClass planner rewrite made that much less predictable than before.
This commit is contained in:
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.230 2007/01/17 17:25:52 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.231 2007/01/22 01:35:20 tgl Exp $
|
||||
*
|
||||
* HISTORY
|
||||
* AUTHOR DATE MAJOR EVENT
|
||||
@@ -64,6 +64,7 @@ typedef struct
|
||||
static bool contain_agg_clause_walker(Node *node, void *context);
|
||||
static bool count_agg_clauses_walker(Node *node, AggClauseCounts *counts);
|
||||
static bool expression_returns_set_walker(Node *node, void *context);
|
||||
static bool expression_returns_set_rows_walker(Node *node, double *count);
|
||||
static bool contain_subplans_walker(Node *node, void *context);
|
||||
static bool contain_mutable_functions_walker(Node *node, void *context);
|
||||
static bool contain_volatile_functions_walker(Node *node, void *context);
|
||||
@@ -566,6 +567,78 @@ expression_returns_set_walker(Node *node, void *context)
|
||||
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.
|
||||
*/
|
||||
double
|
||||
expression_returns_set_rows(Node *clause)
|
||||
{
|
||||
double result = 1;
|
||||
|
||||
(void) expression_returns_set_rows_walker(clause, &result);
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool
|
||||
expression_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
|
||||
*****************************************************************************/
|
||||
|
||||
Reference in New Issue
Block a user