aboutsummaryrefslogtreecommitdiff
path: root/src/backend/optimizer/plan/initsplan.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/optimizer/plan/initsplan.c')
-rw-r--r--src/backend/optimizer/plan/initsplan.c49
1 files changed, 35 insertions, 14 deletions
diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c
index 49c2cdf2f55..1208262b8e4 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.142 2008/08/17 01:19:59 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/plan/initsplan.c,v 1.143 2008/10/21 20:42:53 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -21,6 +21,7 @@
#include "optimizer/joininfo.h"
#include "optimizer/pathnode.h"
#include "optimizer/paths.h"
+#include "optimizer/placeholder.h"
#include "optimizer/planmain.h"
#include "optimizer/prep.h"
#include "optimizer/restrictinfo.h"
@@ -131,7 +132,7 @@ add_base_rels_to_query(PlannerInfo *root, Node *jtnode)
void
build_base_rel_tlists(PlannerInfo *root, List *final_tlist)
{
- List *tlist_vars = pull_var_clause((Node *) final_tlist, false);
+ List *tlist_vars = pull_var_clause((Node *) final_tlist, true);
if (tlist_vars != NIL)
{
@@ -146,6 +147,10 @@ build_base_rel_tlists(PlannerInfo *root, List *final_tlist)
* 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").
+ *
+ * The list may also contain PlaceHolderVars. These don't necessarily
+ * have a single owning relation; we keep their attr_needed info in
+ * root->placeholder_list instead.
*/
void
add_vars_to_targetlist(PlannerInfo *root, List *vars, Relids where_needed)
@@ -156,20 +161,36 @@ add_vars_to_targetlist(PlannerInfo *root, List *vars, Relids where_needed)
foreach(temp, vars)
{
- Var *var = (Var *) lfirst(temp);
- RelOptInfo *rel = find_base_rel(root, var->varno);
- int attrno = var->varattno;
+ Node *node = (Node *) lfirst(temp);
+
+ if (IsA(node, Var))
+ {
+ Var *var = (Var *) node;
+ RelOptInfo *rel = find_base_rel(root, var->varno);
+ int attno = var->varattno;
- Assert(attrno >= rel->min_attr && attrno <= rel->max_attr);
- attrno -= rel->min_attr;
- if (bms_is_empty(rel->attr_needed[attrno]))
+ Assert(attno >= rel->min_attr && attno <= rel->max_attr);
+ attno -= rel->min_attr;
+ if (rel->attr_needed[attno] == NULL)
+ {
+ /* Variable not yet requested, so add to reltargetlist */
+ /* XXX is copyObject necessary here? */
+ rel->reltargetlist = lappend(rel->reltargetlist,
+ copyObject(var));
+ }
+ rel->attr_needed[attno] = bms_add_members(rel->attr_needed[attno],
+ where_needed);
+ }
+ else if (IsA(node, PlaceHolderVar))
{
- /* Variable not yet requested, so add to reltargetlist */
- /* XXX is copyObject necessary here? */
- rel->reltargetlist = lappend(rel->reltargetlist, copyObject(var));
+ PlaceHolderVar *phv = (PlaceHolderVar *) node;
+ PlaceHolderInfo *phinfo = find_placeholder_info(root, phv);
+
+ phinfo->ph_needed = bms_add_members(phinfo->ph_needed,
+ where_needed);
}
- rel->attr_needed[attrno] = bms_add_members(rel->attr_needed[attrno],
- where_needed);
+ else
+ elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
}
}
@@ -934,7 +955,7 @@ distribute_qual_to_rels(PlannerInfo *root, Node *clause,
*/
if (bms_membership(relids) == BMS_MULTIPLE)
{
- List *vars = pull_var_clause(clause, false);
+ List *vars = pull_var_clause(clause, true);
add_vars_to_targetlist(root, vars, relids);
list_free(vars);