*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/util/var.c,v 1.66 2005/10/15 02:49:21 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/util/var.c,v 1.66.2.1 2010/07/08 00:14:27 tgl Exp $
*
*-------------------------------------------------------------------------
*/
{
PlannerInfo *root;
int sublevels_up;
+ bool possible_sublink; /* could aliases include a SubLink? */
+ bool inserted_sublink; /* have we inserted a SubLink? */
} flatten_join_alias_vars_context;
static bool pull_varnos_walker(Node *node,
* is necessary since we will not scan the JOIN as a base relation, which
* is the only way that the executor can directly handle whole-row Vars.
*
+ * If a JOIN contains sub-selects that have been flattened, its join alias
+ * entries might now be arbitrary expressions, not just Vars. This affects
+ * this function in one important way: we might find ourselves inserting
+ * SubLink expressions into subqueries, and we must make sure that their
+ * Query.hasSubLinks fields get set to TRUE if so. If there are any
+ * SubLinks in the join alias lists, the outer Query should already have
+ * hasSubLinks = TRUE, so this is only relevant to un-flattened subqueries.
+ *
* NOTE: this is used on not-yet-planned expressions. We do not expect it
* to be applied directly to a Query node.
*/
context.root = root;
context.sublevels_up = 0;
+ /* flag whether join aliases could possibly contain SubLinks */
+ context.possible_sublink = root->parse->hasSubLinks;
+ /* if hasSubLinks is already true, no need to work hard */
+ context.inserted_sublink = root->parse->hasSubLinks;
return flatten_join_alias_vars_mutator(node, &context);
}
IncrementVarSublevelsUp(newvar, context->sublevels_up, 0);
}
/* Recurse in case join input is itself a join */
+ /* (also takes care of setting inserted_sublink if needed) */
newvar = flatten_join_alias_vars_mutator(newvar, context);
fields = lappend(fields, newvar);
}
newvar = copyObject(newvar);
IncrementVarSublevelsUp(newvar, context->sublevels_up, 0);
}
+
/* Recurse in case join input is itself a join */
- return flatten_join_alias_vars_mutator(newvar, context);
+ newvar = flatten_join_alias_vars_mutator(newvar, context);
+
+ /* Detect if we are adding a sublink to query */
+ if (context->possible_sublink && !context->inserted_sublink)
+ context->inserted_sublink = checkExprHasSubLink(newvar);
+
+ return newvar;
}
if (IsA(node, InClauseInfo))
{
{
/* Recurse into RTE subquery or not-yet-planned sublink subquery */
Query *newnode;
+ bool save_inserted_sublink;
context->sublevels_up++;
+ save_inserted_sublink = context->inserted_sublink;
+ context->inserted_sublink = ((Query *) node)->hasSubLinks;
newnode = query_tree_mutator((Query *) node,
flatten_join_alias_vars_mutator,
(void *) context,
QTW_IGNORE_JOINALIASES);
+ newnode->hasSubLinks |= context->inserted_sublink;
+ context->inserted_sublink = save_inserted_sublink;
context->sublevels_up--;
return (Node *) newnode;
}