summaryrefslogtreecommitdiff
path: root/src/backend/optimizer/plan/initsplan.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2003-06-29 23:05:05 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2003-06-29 23:05:05 +0000
commit835bb975d8d11268582d9dbd26b0eeaa62b60632 (patch)
tree5d5d3d57acfe7627235aa72c28c37d8c85b210a3 /src/backend/optimizer/plan/initsplan.c
parentcf883ea95c4bad69910300cbd6c0ef5cb84a9178 (diff)
Restructure building of join relation targetlists so that a join plan
node emits only those vars that are actually needed above it in the plan tree. (There were comments in the code suggesting that this was done at some point in the dim past, but for a long time we have just made join nodes emit everything that either input emitted.) Aside from being marginally more efficient, this fixes the problem noted by Peter Eisentraut where a join above an IN-implemented-as-join might fail, because the subplan targetlist constructed in the latter case didn't meet the expectation of including everything. Along the way, fix some places that were O(N^2) in the targetlist length. This is not all the trouble spots for wide queries by any means, but it's a step forward.
Diffstat (limited to 'src/backend/optimizer/plan/initsplan.c')
-rw-r--r--src/backend/optimizer/plan/initsplan.c45
1 files changed, 33 insertions, 12 deletions
diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c
index 05d963d94c1..cbc1ff365a3 100644
--- a/src/backend/optimizer/plan/initsplan.c
+++ b/src/backend/optimizer/plan/initsplan.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/initsplan.c,v 1.85 2003/03/02 23:46:34 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/initsplan.c,v 1.86 2003/06/29 23:05:04 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -40,7 +40,8 @@ static void distribute_qual_to_rels(Query *root, Node *clause,
bool isdeduced,
Relids outerjoin_nonnullable,
Relids qualscope);
-static void add_vars_to_targetlist(Query *root, List *vars);
+static void add_vars_to_targetlist(Query *root, List *vars,
+ Relids where_needed);
static bool qual_is_redundant(Query *root, RestrictInfo *restrictinfo,
List *restrictlist);
static void check_mergejoinable(RestrictInfo *restrictinfo);
@@ -112,34 +113,54 @@ add_base_rels_to_query(Query *root, Node *jtnode)
/*
* build_base_rel_tlists
- * Creates targetlist entries for each var seen in 'tlist' and adds
- * them to the tlist of the appropriate rel node.
+ * Add targetlist entries for each var needed in the query's final tlist
+ * to the appropriate base relations.
+ *
+ * We mark such vars as needed by "relation 0" to ensure that they will
+ * propagate up through all join plan steps.
*/
void
-build_base_rel_tlists(Query *root, List *tlist)
+build_base_rel_tlists(Query *root, List *final_tlist)
{
- List *tlist_vars = pull_var_clause((Node *) tlist, false);
+ List *tlist_vars = pull_var_clause((Node *) final_tlist, false);
- add_vars_to_targetlist(root, tlist_vars);
- freeList(tlist_vars);
+ if (tlist_vars != NIL)
+ {
+ add_vars_to_targetlist(root, tlist_vars, bms_make_singleton(0));
+ freeList(tlist_vars);
+ }
}
/*
* add_vars_to_targetlist
* For each variable appearing in the list, add it to the owning
- * relation's targetlist if not already present.
+ * relation's targetlist if not already present, and mark the variable
+ * as being needed for the indicated join (or for final output if
+ * where_needed includes "relation 0").
*/
static void
-add_vars_to_targetlist(Query *root, List *vars)
+add_vars_to_targetlist(Query *root, List *vars, Relids where_needed)
{
List *temp;
+ Assert(!bms_is_empty(where_needed));
+
foreach(temp, vars)
{
Var *var = (Var *) lfirst(temp);
RelOptInfo *rel = find_base_rel(root, var->varno);
+ int attrno = var->varattno;
- add_var_to_tlist(rel, var);
+ Assert(attrno >= rel->min_attr && attrno <= rel->max_attr);
+ attrno -= rel->min_attr;
+ if (bms_is_empty(rel->attr_needed[attrno]))
+ {
+ /* Variable not yet requested, so add to reltargetlist */
+ /* XXX is copyObject necessary here? */
+ FastAppend(&rel->reltargetlist, copyObject(var));
+ }
+ rel->attr_needed[attrno] = bms_add_members(rel->attr_needed[attrno],
+ where_needed);
}
}
@@ -575,7 +596,7 @@ distribute_qual_to_rels(Query *root, Node *clause,
* scan those relations (else they won't be available at the join
* node!).
*/
- add_vars_to_targetlist(root, vars);
+ add_vars_to_targetlist(root, vars, relids);
break;
default:
/*