1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-02 09:02:37 +03:00

Allow merge and hash joins to occur on arbitrary expressions (anything not

containing a volatile function), rather than only on 'Var = Var' clauses
as before.  This makes it practical to do flatten_join_alias_vars at the
start of planning, which in turn eliminates a bunch of klugery inside the
planner to deal with alias vars.  As a free side effect, we now detect
implied equality of non-Var expressions; for example in
	SELECT ... WHERE a.x = b.y and b.y = 42
we will deduce a.x = 42 and use that as a restriction qual on a.  Also,
we can remove the restriction introduced 12/5/02 to prevent pullup of
subqueries whose targetlists contain sublinks.
Still TODO: make statistical estimation routines in selfuncs.c and costsize.c
smarter about expressions that are more complex than plain Vars.  The need
for this is considerably greater now that we have to be able to estimate
the suitability of merge and hash join techniques on such expressions.
This commit is contained in:
Tom Lane
2003-01-15 19:35:48 +00:00
parent 0eed62f34d
commit de97072e3c
32 changed files with 523 additions and 662 deletions

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/var.c,v 1.43 2003/01/10 21:08:13 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/var.c,v 1.44 2003/01/15 19:35:44 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -20,6 +20,16 @@
#include "parser/parsetree.h"
/* macros borrowed from expression_tree_mutator */
#define FLATCOPY(newnode, node, nodetype) \
( (newnode) = makeNode(nodetype), \
memcpy((newnode), (node), sizeof(nodetype)) )
#define MUTATE(newfield, oldfield, fieldtype, mutator, context) \
( (newfield) = (fieldtype) mutator((Node *) (oldfield), (context)) )
typedef struct
{
List *varlist;
@ -42,7 +52,7 @@ typedef struct
typedef struct
{
List *rtable;
bool force;
int sublevels_up;
} flatten_join_alias_vars_context;
static bool pull_varnos_walker(Node *node,
@ -314,26 +324,16 @@ pull_var_clause_walker(Node *node, pull_var_clause_context *context)
* relation variables instead. This allows quals involving such vars to be
* pushed down.
*
* If force is TRUE then we will reduce all JOIN alias Vars to non-alias Vars
* or expressions thereof (there may be COALESCE and/or type conversions
* involved). If force is FALSE we will not expand a Var to a non-Var
* expression. This is a hack to avoid confusing mergejoin planning, which
* currently cannot cope with non-Var join items --- we leave the join vars
* as Vars till after planning is done, then expand them during setrefs.c.
*
* Upper-level vars (with varlevelsup > 0) are ignored; normally there
* should not be any by the time this routine is called.
*
* Does not examine subqueries, therefore must only be used after reduction
* of sublinks to subplans!
* NOTE: this is used on not-yet-planned expressions. We do not expect it
* to be applied directly to a Query node.
*/
Node *
flatten_join_alias_vars(Node *node, List *rtable, bool force)
flatten_join_alias_vars(Node *node, List *rtable)
{
flatten_join_alias_vars_context context;
context.rtable = rtable;
context.force = force;
context.sublevels_up = 0;
return flatten_join_alias_vars_mutator(node, &context);
}
@ -350,21 +350,31 @@ flatten_join_alias_vars_mutator(Node *node,
RangeTblEntry *rte;
Node *newvar;
if (var->varlevelsup != 0)
if (var->varlevelsup != context->sublevels_up)
return node; /* no need to copy, really */
rte = rt_fetch(var->varno, context->rtable);
if (rte->rtekind != RTE_JOIN)
return node;
Assert(var->varattno > 0);
newvar = (Node *) nth(var->varattno - 1, rte->joinaliasvars);
if (IsA(newvar, Var) ||context->force)
{
/* expand it; recurse in case join input is itself a join */
return flatten_join_alias_vars_mutator(newvar, context);
}
/* we don't want to force expansion of this alias Var */
return node;
/* expand it; recurse in case join input is itself a join */
return flatten_join_alias_vars_mutator(newvar, context);
}
if (IsA(node, Query))
{
/* Recurse into RTE subquery or not-yet-planned sublink subquery */
Query *query = (Query *) node;
Query *newnode;
FLATCOPY(newnode, query, Query);
context->sublevels_up++;
query_tree_mutator(newnode, flatten_join_alias_vars_mutator,
(void *) context, QTW_IGNORE_JOINALIASES);
context->sublevels_up--;
return (Node *) newnode;
}
/* Already-planned tree not supported */
Assert(!is_subplan(node));
return expression_tree_mutator(node, flatten_join_alias_vars_mutator,
(void *) context);
}