diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/optimizer/plan/initsplan.c | 36 | ||||
-rw-r--r-- | src/backend/optimizer/plan/planmain.c | 9 | ||||
-rw-r--r-- | src/include/optimizer/planmain.h | 3 |
3 files changed, 45 insertions, 3 deletions
diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c index b1e69b7b3a5..25efaf59d7d 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.91.2.3 2005/09/28 21:17:48 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/initsplan.c,v 1.91.2.4 2007/10/04 20:45:17 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -126,6 +126,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) +{ + List *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)); + freeList(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 a8159dd972b..94365808b84 100644 --- a/src/backend/optimizer/plan/planmain.c +++ b/src/backend/optimizer/plan/planmain.c @@ -14,7 +14,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planmain.c,v 1.78.4.1 2005/09/28 21:17:49 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planmain.c,v 1.78.4.2 2007/10/04 20:45:17 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 d288c4e3374..1b252a8f63d 100644 --- a/src/include/optimizer/planmain.h +++ b/src/include/optimizer/planmain.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: planmain.h,v 1.75.4.1 2005/09/28 21:17:50 tgl Exp $ + * $Id: planmain.h,v 1.75.4.2 2007/10/04 20:45:17 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -57,6 +57,7 @@ extern Result *make_result(List *tlist, Node *resconstantqual, Plan *subplan); */ 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, |