88 *
99 *
1010 * IDENTIFICATION
11- * $PostgreSQL: pgsql/src/backend/optimizer/util/var.c,v 1.63 2004/12/31 22: 00:23 pgsql Exp $
11+ * $PostgreSQL: pgsql/src/backend/optimizer/util/var.c,v 1.63.4.1 2010/07/08 00:14:33 tgl Exp $
1212 *
1313 *-------------------------------------------------------------------------
1414 */
@@ -51,6 +51,8 @@ typedef struct
5151{
5252 Query * root ;
5353 int sublevels_up ;
54+ bool possible_sublink ; /* could aliases include a SubLink? */
55+ bool inserted_sublink ; /* have we inserted a SubLink? */
5456} flatten_join_alias_vars_context ;
5557
5658static bool pull_varnos_walker (Node * node ,
@@ -478,6 +480,14 @@ pull_var_clause_walker(Node *node, pull_var_clause_context *context)
478480 * is necessary since we will not scan the JOIN as a base relation, which
479481 * is the only way that the executor can directly handle whole-row Vars.
480482 *
483+ * If a JOIN contains sub-selects that have been flattened, its join alias
484+ * entries might now be arbitrary expressions, not just Vars. This affects
485+ * this function in one important way: we might find ourselves inserting
486+ * SubLink expressions into subqueries, and we must make sure that their
487+ * Query.hasSubLinks fields get set to TRUE if so. If there are any
488+ * SubLinks in the join alias lists, the outer Query should already have
489+ * hasSubLinks = TRUE, so this is only relevant to un-flattened subqueries.
490+ *
481491 * NOTE: this is used on not-yet-planned expressions. We do not expect it
482492 * to be applied directly to a Query node.
483493 */
@@ -488,6 +498,10 @@ flatten_join_alias_vars(Query *root, Node *node)
488498
489499 context .root = root ;
490500 context .sublevels_up = 0 ;
501+ /* flag whether join aliases could possibly contain SubLinks */
502+ context .possible_sublink = root -> hasSubLinks ;
503+ /* if hasSubLinks is already true, no need to work hard */
504+ context .inserted_sublink = root -> hasSubLinks ;
491505
492506 return flatten_join_alias_vars_mutator (node , & context );
493507}
@@ -539,6 +553,7 @@ flatten_join_alias_vars_mutator(Node *node,
539553 IncrementVarSublevelsUp (newvar , context -> sublevels_up , 0 );
540554 }
541555 /* Recurse in case join input is itself a join */
556+ /* (also takes care of setting inserted_sublink if needed) */
542557 newvar = flatten_join_alias_vars_mutator (newvar , context );
543558 fields = lappend (fields , newvar );
544559 }
@@ -563,8 +578,15 @@ flatten_join_alias_vars_mutator(Node *node,
563578 newvar = copyObject (newvar );
564579 IncrementVarSublevelsUp (newvar , context -> sublevels_up , 0 );
565580 }
581+
566582 /* Recurse in case join input is itself a join */
567- return flatten_join_alias_vars_mutator (newvar , context );
583+ newvar = flatten_join_alias_vars_mutator (newvar , context );
584+
585+ /* Detect if we are adding a sublink to query */
586+ if (context -> possible_sublink && !context -> inserted_sublink )
587+ context -> inserted_sublink = checkExprHasSubLink (newvar );
588+
589+ return newvar ;
568590 }
569591 if (IsA (node , InClauseInfo ))
570592 {
@@ -589,12 +611,17 @@ flatten_join_alias_vars_mutator(Node *node,
589611 {
590612 /* Recurse into RTE subquery or not-yet-planned sublink subquery */
591613 Query * newnode ;
614+ bool save_inserted_sublink ;
592615
593616 context -> sublevels_up ++ ;
617+ save_inserted_sublink = context -> inserted_sublink ;
618+ context -> inserted_sublink = ((Query * ) node )-> hasSubLinks ;
594619 newnode = query_tree_mutator ((Query * ) node ,
595620 flatten_join_alias_vars_mutator ,
596621 (void * ) context ,
597622 QTW_IGNORE_JOINALIASES );
623+ newnode -> hasSubLinks |= context -> inserted_sublink ;
624+ context -> inserted_sublink = save_inserted_sublink ;
598625 context -> sublevels_up -- ;
599626 return (Node * ) newnode ;
600627 }
0 commit comments