Commit b5956a2f authored by Tom Lane's avatar Tom Lane

Detect case where an outer join can be reduced to a plain inner join

because there are WHERE clauses that will reject the null-extended rows.
Per suggestion from Brandon Craig Rhodes, 19-Nov-02.
parent 43785a43
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.145 2003/02/09 00:30:39 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.146 2003/02/09 23:57:19 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -144,6 +144,7 @@ subquery_planner(Query *parse, double tuple_fraction) ...@@ -144,6 +144,7 @@ subquery_planner(Query *parse, double tuple_fraction)
{ {
List *saved_initplan = PlannerInitPlan; List *saved_initplan = PlannerInitPlan;
int saved_planid = PlannerPlanId; int saved_planid = PlannerPlanId;
bool hasOuterJoins;
Plan *plan; Plan *plan;
List *newHaving; List *newHaving;
List *lst; List *lst;
...@@ -172,10 +173,12 @@ subquery_planner(Query *parse, double tuple_fraction) ...@@ -172,10 +173,12 @@ subquery_planner(Query *parse, double tuple_fraction)
/* /*
* Detect whether any rangetable entries are RTE_JOIN kind; if not, * Detect whether any rangetable entries are RTE_JOIN kind; if not,
* we can avoid the expense of doing flatten_join_alias_vars(). * we can avoid the expense of doing flatten_join_alias_vars(). Also
* check for outer joins --- if none, we can skip reduce_outer_joins().
* This must be done after we have done pull_up_subqueries, of course. * This must be done after we have done pull_up_subqueries, of course.
*/ */
parse->hasJoinRTEs = false; parse->hasJoinRTEs = false;
hasOuterJoins = false;
foreach(lst, parse->rtable) foreach(lst, parse->rtable)
{ {
RangeTblEntry *rte = (RangeTblEntry *) lfirst(lst); RangeTblEntry *rte = (RangeTblEntry *) lfirst(lst);
...@@ -183,9 +186,14 @@ subquery_planner(Query *parse, double tuple_fraction) ...@@ -183,9 +186,14 @@ subquery_planner(Query *parse, double tuple_fraction)
if (rte->rtekind == RTE_JOIN) if (rte->rtekind == RTE_JOIN)
{ {
parse->hasJoinRTEs = true; parse->hasJoinRTEs = true;
if (IS_OUTER_JOIN(rte->jointype))
{
hasOuterJoins = true;
/* Can quit scanning once we find an outer join */
break; break;
} }
} }
}
/* /*
* Do expression preprocessing on targetlist and quals. * Do expression preprocessing on targetlist and quals.
...@@ -244,15 +252,23 @@ subquery_planner(Query *parse, double tuple_fraction) ...@@ -244,15 +252,23 @@ subquery_planner(Query *parse, double tuple_fraction)
} }
parse->havingQual = (Node *) newHaving; parse->havingQual = (Node *) newHaving;
/*
* If we have any outer joins, try to reduce them to plain inner joins.
* This step is most easily done after we've done expression preprocessing.
*/
if (hasOuterJoins)
reduce_outer_joins(parse);
/* /*
* See if we can simplify the jointree; opportunities for this may come * See if we can simplify the jointree; opportunities for this may come
* from having pulled up subqueries, or from flattening explicit JOIN * from having pulled up subqueries, or from flattening explicit JOIN
* syntax. We must do this after flattening JOIN alias variables, since * syntax. We must do this after flattening JOIN alias variables, since
* eliminating explicit JOIN nodes from the jointree will cause * eliminating explicit JOIN nodes from the jointree will cause
* get_relids_for_join() to fail. * get_relids_for_join() to fail. But it should happen after
* reduce_outer_joins, anyway.
*/ */
parse->jointree = (FromExpr *) parse->jointree = (FromExpr *)
preprocess_jointree(parse, (Node *) parse->jointree); simplify_jointree(parse, (Node *) parse->jointree);
/* /*
* Do the main planning. If we have an inherited target relation, * Do the main planning. If we have an inherited target relation,
......
This diff is collapsed.
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: prep.h,v 1.36 2003/02/08 20:20:55 tgl Exp $ * $Id: prep.h,v 1.37 2003/02/09 23:57:19 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -28,7 +28,8 @@ extern int join_collapse_limit; ...@@ -28,7 +28,8 @@ extern int join_collapse_limit;
extern Node *pull_up_IN_clauses(Query *parse, Node *node); extern Node *pull_up_IN_clauses(Query *parse, Node *node);
extern Node *pull_up_subqueries(Query *parse, Node *jtnode, extern Node *pull_up_subqueries(Query *parse, Node *jtnode,
bool below_outer_join); bool below_outer_join);
extern Node *preprocess_jointree(Query *parse, Node *jtnode); extern void reduce_outer_joins(Query *parse);
extern Node *simplify_jointree(Query *parse, Node *jtnode);
extern Relids get_relids_in_jointree(Node *jtnode); extern Relids get_relids_in_jointree(Node *jtnode);
extern Relids get_relids_for_join(Query *parse, int joinrelid); extern Relids get_relids_for_join(Query *parse, int joinrelid);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment