summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/optimizer/plan/initsplan.c36
-rw-r--r--src/backend/optimizer/plan/planmain.c9
-rw-r--r--src/include/optimizer/planmain.h3
3 files changed, 45 insertions, 3 deletions
diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c
index f55adc85915..b6993f64c05 100644
--- a/src/backend/optimizer/plan/initsplan.c
+++ b/src/backend/optimizer/plan/initsplan.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/plan/initsplan.c,v 1.104.4.1 2005/09/28 21:17:23 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/plan/initsplan.c,v 1.104.4.2 2007/10/04 20:45:09 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -127,6 +127,40 @@ build_base_rel_tlists(Query *root, List *final_tlist)
}
/*
+ * add_IN_vars_to_tlists
+ * Add targetlist entries for each var needed in InClauseInfo entries
+ * to the appropriate base relations.
+ *
+ * Normally this is a waste of time because scanning of the WHERE clause
+ * will have added them. But it is possible that eval_const_expressions()
+ * simplified away all references to the vars after the InClauseInfos were
+ * made. We need the IN's righthand-side vars to be available at the join
+ * anyway, in case we try to unique-ify the subselect's outputs. (The only
+ * known case that provokes this is "WHERE false AND foo IN (SELECT ...)".
+ * We don't try to be very smart about such cases, just correct.)
+ */
+void
+add_IN_vars_to_tlists(Query *root)
+{
+ ListCell *l;
+
+ foreach(l, root->in_info_list)
+ {
+ InClauseInfo *ininfo = (InClauseInfo *) lfirst(l);
+ List *in_vars;
+
+ in_vars = pull_var_clause((Node *) ininfo->sub_targetlist, false);
+ if (in_vars != NIL)
+ {
+ add_vars_to_targetlist(root, in_vars,
+ bms_union(ininfo->lefthand,
+ ininfo->righthand));
+ list_free(in_vars);
+ }
+ }
+}
+
+/*
* add_vars_to_targetlist
* For each variable appearing in the list, add it to the owning
* relation's targetlist if not already present, and mark the variable
diff --git a/src/backend/optimizer/plan/planmain.c b/src/backend/optimizer/plan/planmain.c
index 7ad11ee3226..b7898ad1759 100644
--- a/src/backend/optimizer/plan/planmain.c
+++ b/src/backend/optimizer/plan/planmain.c
@@ -14,7 +14,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/plan/planmain.c,v 1.81.4.1 2005/09/28 21:17:23 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/plan/planmain.c,v 1.81.4.2 2007/10/04 20:45:09 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -136,6 +136,13 @@ query_planner(Query *root, List *tlist, double tuple_fraction,
(void) distribute_quals_to_rels(root, (Node *) root->jointree, false);
/*
+ * Vars mentioned in InClauseInfo items also have to be added to baserel
+ * targetlists. Nearly always, they'd have got there from the original
+ * WHERE qual, but in corner cases maybe not.
+ */
+ add_IN_vars_to_tlists(root);
+
+ /*
* Use the completed lists of equijoined keys to deduce any implied
* but unstated equalities (for example, A=B and B=C imply A=C).
*/
diff --git a/src/include/optimizer/planmain.h b/src/include/optimizer/planmain.h
index 9c359b499f6..0a0d3fc95cf 100644
--- a/src/include/optimizer/planmain.h
+++ b/src/include/optimizer/planmain.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/optimizer/planmain.h,v 1.79.4.1 2005/09/28 21:17:24 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/optimizer/planmain.h,v 1.79.4.2 2007/10/04 20:45:09 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -57,6 +57,7 @@ extern bool is_projection_capable_plan(Plan *plan);
*/
extern void add_base_rels_to_query(Query *root, Node *jtnode);
extern void build_base_rel_tlists(Query *root, List *final_tlist);
+extern void add_IN_vars_to_tlists(Query *root);
extern Relids distribute_quals_to_rels(Query *root, Node *jtnode,
bool below_outer_join);
extern void process_implied_equality(Query *root,