1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-06 07:49:08 +03:00

Further work on planning of indexscans. Cleaned up interfaces

to index_selectivity so that it can be handed an indexqual clause list
rather than a bunch of assorted derivative data.
This commit is contained in:
Tom Lane
1999-07-25 23:07:26 +00:00
parent 8ae29a1d40
commit 49ed4dd779
11 changed files with 319 additions and 497 deletions

View File

@@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.41 1999/07/24 23:21:13 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.42 1999/07/25 23:07:25 tgl Exp $
*
* HISTORY
* AUTHOR DATE MAJOR EVENT
@@ -29,6 +29,7 @@
static bool fix_opid_walker(Node *node, void *context);
static int is_single_func(Node *node);
Expr *
@@ -533,36 +534,36 @@ fix_opids(List *clauses)
/*
* get_relattval
* For a non-join clause, returns a list consisting of the
* relid,
* attno,
* value of the CONST node (if any), and a
* flag indicating whether the value appears on the left or right
* of the operator and whether the value varied.
*
* OLD OBSOLETE COMMENT FOLLOWS:
* If 'clause' is not of the format (op var node) or (op node var),
* or if the var refers to a nested attribute, then -1's are returned for
* everything but the value a blank string "" (pointer to \0) is
* returned for the value if it is unknown or null.
* END OF OLD OBSOLETE COMMENT.
* NEW COMMENT:
* when defining rules one of the attributes of the operator can
* be a Param node (which is supposed to be treated as a constant).
* However as there is no value specified for a parameter until run time
* this routine used to return "" as value, which caused 'compute_selec'
* to bomb (because it was expecting a lisp integer and got back a lisp
* string). Now the code returns a plain old good "lispInteger(0)".
* Extract information from a restriction or join clause for
* selectivity estimation. The inputs are an expression
* and a relation number (which can be 0 if we don't care which
* relation is used; that'd normally be the case for restriction
* clauses, where the caller already knows that only one relation
* 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
* returns the following info:
* the found relation number (same as targetrelid unless that is 0)
* the found var number (or InvalidAttrNumber if a function)
* if the "something" is a constant, the value of the constant
* flags indicating whether a constant was found, and on which side.
* Default values are returned if the expression is too complicated,
* specifically -1 for the relid and attno, 0 for the constant value.
* Note that InvalidAttrNumber is *not* -1, but 0.
*/
void
get_relattval(Node *clause,
int targetrelid,
int *relid,
AttrNumber *attno,
Datum *constval,
int *flag)
{
Var *left,
*right;
*right,
*other;
int funcvarno;
/* Careful; the passed clause might not be a binary operator at all */
@@ -575,71 +576,96 @@ get_relattval(Node *clause,
if (!right)
goto default_results;
if (IsA(left, Var) &&IsA(right, Const))
/* First look for the var or func */
if (IsA(left, Var) &&
(targetrelid == 0 || targetrelid == left->varno))
{
*relid = left->varno;
*attno = left->varattno;
*constval = ((Const *) right)->constvalue;
*flag = (_SELEC_CONSTANT_RIGHT_ | _SELEC_IS_CONSTANT_);
*flag = SEL_RIGHT;
}
else if (IsA(left, Var) &&IsA(right, Param))
{
*relid = left->varno;
*attno = left->varattno;
*constval = 0;
*flag = (_SELEC_NOT_CONSTANT_);
}
else if (is_funcclause((Node *) left) && IsA(right, Const))
{
List *vars = pull_var_clause((Node *) left);
*relid = ((Var *) lfirst(vars))->varno;
*attno = InvalidAttrNumber;
*constval = ((Const *) right)->constvalue;
*flag = (_SELEC_CONSTANT_RIGHT_ | _SELEC_IS_CONSTANT_);
}
else if (IsA(right, Var) &&IsA(left, Const))
else if (IsA(right, Var) &&
(targetrelid == 0 || targetrelid == right->varno))
{
*relid = right->varno;
*attno = right->varattno;
*constval = ((Const *) left)->constvalue;
*flag = (_SELEC_IS_CONSTANT_);
*flag = 0;
}
else if (IsA(right, Var) &&IsA(left, Param))
else if ((funcvarno = is_single_func((Node *) left)) != 0 &&
(targetrelid == 0 || targetrelid == funcvarno))
{
*relid = right->varno;
*attno = right->varattno;
*constval = 0;
*flag = (_SELEC_NOT_CONSTANT_);
}
else if (is_funcclause((Node *) right) && IsA(left, Const))
{
List *vars = pull_var_clause((Node *) right);
*relid = ((Var *) lfirst(vars))->varno;
*relid = funcvarno;
*attno = InvalidAttrNumber;
*constval = ((Const *) left)->constvalue;
*flag = (_SELEC_IS_CONSTANT_);
*flag = SEL_RIGHT;
}
else if ((funcvarno = is_single_func((Node *) right)) != 0 &&
(targetrelid == 0 || targetrelid == funcvarno))
{
*relid = funcvarno;
*attno = InvalidAttrNumber;
*flag = 0;
}
else
{
/* Duh, it's too complicated for me... */
default_results:
*relid = _SELEC_VALUE_UNKNOWN_;
*attno = _SELEC_VALUE_UNKNOWN_;
*relid = -1;
*attno = -1;
*constval = 0;
*flag = 0;
return;
}
/* OK, we identified the var or func; now look at the other side */
other = (*flag == 0) ? left : right;
if (IsA(other, Const))
{
*constval = ((Const *) other)->constvalue;
*flag |= SEL_CONSTANT;
}
else
{
*constval = 0;
*flag = (_SELEC_NOT_CONSTANT_);
}
}
/*
* get_relsatts
* is_single_func
* 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)
{
if (is_funcclause(node))
{
List *vars = pull_var_clause(node);
if (vars != NIL)
{
int funcvarno = ((Var *) lfirst(vars))->varno;
/* need to check that all args of func are same relation */
while ((vars = lnext(vars)) != NIL)
{
if (((Var *) lfirst(vars))->varno != funcvarno)
return 0;
}
return funcvarno;
}
}
return 0;
}
/*
* get_rels_atts
*
* Returns a list
* Returns the info
* ( relid1 attno1 relid2 attno2 )
* for a joinclause.
*
* If the clause is not of the form (op var var) or if any of the vars
* If the clause is not of the form (var op var) or if any of the vars
* refer to nested attributes, then -1's are returned.
*
*/
@@ -650,6 +676,12 @@ get_rels_atts(Node *clause,
int *relid2,
AttrNumber *attno2)
{
/* set default values */
*relid1 = -1;
*attno1 = -1;
*relid2 = -1;
*attno2 = -1;
if (is_opclause(clause))
{
Var *left = get_leftop((Expr *) clause);
@@ -657,47 +689,31 @@ get_rels_atts(Node *clause,
if (left && right)
{
bool var_left = IsA(left, Var);
bool var_right = IsA(right, Var);
bool varexpr_left = (bool) ((IsA(left, Func) ||IsA(left, Oper)) &&
contain_var_clause((Node *) left));
bool varexpr_right = (bool) ((IsA(right, Func) ||IsA(right, Oper)) &&
contain_var_clause((Node *) right));
int funcvarno;
if (var_left && var_right)
if (IsA(left, Var))
{
*relid1 = left->varno;
*attno1 = left->varoattno;
*relid2 = right->varno;
*attno2 = right->varoattno;
return;
*attno1 = left->varattno;
}
if (var_left && varexpr_right)
else if ((funcvarno = is_single_func((Node *) left)) != 0)
{
*relid1 = left->varno;
*attno1 = left->varoattno;
*relid2 = _SELEC_VALUE_UNKNOWN_;
*attno2 = _SELEC_VALUE_UNKNOWN_;
return;
*relid1 = funcvarno;
*attno1 = InvalidAttrNumber;
}
if (varexpr_left && var_right)
{
*relid1 = _SELEC_VALUE_UNKNOWN_;
*attno1 = _SELEC_VALUE_UNKNOWN_;
if (IsA(right, Var))
{
*relid2 = right->varno;
*attno2 = right->varoattno;
return;
*attno2 = right->varattno;
}
else if ((funcvarno = is_single_func((Node *) right)) != 0)
{
*relid2 = funcvarno;
*attno2 = InvalidAttrNumber;
}
}
}
*relid1 = _SELEC_VALUE_UNKNOWN_;
*attno1 = _SELEC_VALUE_UNKNOWN_;
*relid2 = _SELEC_VALUE_UNKNOWN_;
*attno2 = _SELEC_VALUE_UNKNOWN_;
}
/*--------------------