1414 *
1515 *
1616 * IDENTIFICATION
17- * $PostgreSQL: pgsql/src/backend/optimizer/util/var.c,v 1.87 2010/01/02 16:57:48 momjian Exp $
17+ * $PostgreSQL: pgsql/src/backend/optimizer/util/var.c,v 1.88 2010/07/08 00:14:03 tgl Exp $
1818 *
1919 *-------------------------------------------------------------------------
2020 */
@@ -63,6 +63,8 @@ typedef struct
6363{
6464 PlannerInfo * root ;
6565 int sublevels_up ;
66+ bool possible_sublink ; /* could aliases include a SubLink? */
67+ bool inserted_sublink ; /* have we inserted a SubLink? */
6668} flatten_join_alias_vars_context ;
6769
6870static bool pull_varnos_walker (Node * node ,
@@ -688,6 +690,14 @@ pull_var_clause_walker(Node *node, pull_var_clause_context *context)
688690 * This also adjusts relid sets found in some expression node types to
689691 * substitute the contained base rels for any join relid.
690692 *
693+ * If a JOIN contains sub-selects that have been flattened, its join alias
694+ * entries might now be arbitrary expressions, not just Vars. This affects
695+ * this function in one important way: we might find ourselves inserting
696+ * SubLink expressions into subqueries, and we must make sure that their
697+ * Query.hasSubLinks fields get set to TRUE if so. If there are any
698+ * SubLinks in the join alias lists, the outer Query should already have
699+ * hasSubLinks = TRUE, so this is only relevant to un-flattened subqueries.
700+ *
691701 * NOTE: this is used on not-yet-planned expressions. We do not expect it
692702 * to be applied directly to a Query node.
693703 */
@@ -698,6 +708,10 @@ flatten_join_alias_vars(PlannerInfo *root, Node *node)
698708
699709 context .root = root ;
700710 context .sublevels_up = 0 ;
711+ /* flag whether join aliases could possibly contain SubLinks */
712+ context .possible_sublink = root -> parse -> hasSubLinks ;
713+ /* if hasSubLinks is already true, no need to work hard */
714+ context .inserted_sublink = root -> parse -> hasSubLinks ;
701715
702716 return flatten_join_alias_vars_mutator (node , & context );
703717}
@@ -747,6 +761,7 @@ flatten_join_alias_vars_mutator(Node *node,
747761 IncrementVarSublevelsUp (newvar , context -> sublevels_up , 0 );
748762 }
749763 /* Recurse in case join input is itself a join */
764+ /* (also takes care of setting inserted_sublink if needed) */
750765 newvar = flatten_join_alias_vars_mutator (newvar , context );
751766 fields = lappend (fields , newvar );
752767 }
@@ -773,8 +788,15 @@ flatten_join_alias_vars_mutator(Node *node,
773788 newvar = copyObject (newvar );
774789 IncrementVarSublevelsUp (newvar , context -> sublevels_up , 0 );
775790 }
791+
776792 /* Recurse in case join input is itself a join */
777- return flatten_join_alias_vars_mutator (newvar , context );
793+ newvar = flatten_join_alias_vars_mutator (newvar , context );
794+
795+ /* Detect if we are adding a sublink to query */
796+ if (context -> possible_sublink && !context -> inserted_sublink )
797+ context -> inserted_sublink = checkExprHasSubLink (newvar );
798+
799+ return newvar ;
778800 }
779801 if (IsA (node , PlaceHolderVar ))
780802 {
@@ -797,12 +819,17 @@ flatten_join_alias_vars_mutator(Node *node,
797819 {
798820 /* Recurse into RTE subquery or not-yet-planned sublink subquery */
799821 Query * newnode ;
822+ bool save_inserted_sublink ;
800823
801824 context -> sublevels_up ++ ;
825+ save_inserted_sublink = context -> inserted_sublink ;
826+ context -> inserted_sublink = ((Query * ) node )-> hasSubLinks ;
802827 newnode = query_tree_mutator ((Query * ) node ,
803828 flatten_join_alias_vars_mutator ,
804829 (void * ) context ,
805830 QTW_IGNORE_JOINALIASES );
831+ newnode -> hasSubLinks |= context -> inserted_sublink ;
832+ context -> inserted_sublink = save_inserted_sublink ;
806833 context -> sublevels_up -- ;
807834 return (Node * ) newnode ;
808835 }
0 commit comments