@@ -148,6 +148,65 @@ replace_outer_var(PlannerInfo *root, Var *var)
148
148
return retval ;
149
149
}
150
150
151
+ /*
152
+ * Generate a Param node to replace the given PlaceHolderVar,
153
+ * which is expected to have phlevelsup > 0 (ie, it is not local).
154
+ *
155
+ * This is just like replace_outer_var, except for PlaceHolderVars.
156
+ */
157
+ static Param *
158
+ replace_outer_placeholdervar (PlannerInfo * root , PlaceHolderVar * phv )
159
+ {
160
+ Param * retval ;
161
+ ListCell * ppl ;
162
+ PlannerParamItem * pitem ;
163
+ Index abslevel ;
164
+ int i ;
165
+
166
+ Assert (phv -> phlevelsup > 0 && phv -> phlevelsup < root -> query_level );
167
+ abslevel = root -> query_level - phv -> phlevelsup ;
168
+
169
+ /* If there's already a paramlist entry for this same PHV, just use it */
170
+ i = 0 ;
171
+ foreach (ppl , root -> glob -> paramlist )
172
+ {
173
+ pitem = (PlannerParamItem * ) lfirst (ppl );
174
+ if (pitem -> abslevel == abslevel && IsA (pitem -> item , PlaceHolderVar ))
175
+ {
176
+ PlaceHolderVar * pphv = (PlaceHolderVar * ) pitem -> item ;
177
+
178
+ /* We assume comparing the PHIDs is sufficient */
179
+ if (pphv -> phid == phv -> phid )
180
+ break ;
181
+ }
182
+ i ++ ;
183
+ }
184
+
185
+ if (!ppl )
186
+ {
187
+ /* Nope, so make a new one */
188
+ phv = (PlaceHolderVar * ) copyObject (phv );
189
+ IncrementVarSublevelsUp ((Node * ) phv , - ((int ) phv -> phlevelsup ), 0 );
190
+ Assert (phv -> phlevelsup == 0 );
191
+
192
+ pitem = makeNode (PlannerParamItem );
193
+ pitem -> item = (Node * ) phv ;
194
+ pitem -> abslevel = abslevel ;
195
+
196
+ root -> glob -> paramlist = lappend (root -> glob -> paramlist , pitem );
197
+ /* i is already the correct index for the new item */
198
+ }
199
+
200
+ retval = makeNode (Param );
201
+ retval -> paramkind = PARAM_EXEC ;
202
+ retval -> paramid = i ;
203
+ retval -> paramtype = exprType ((Node * ) phv -> phexpr );
204
+ retval -> paramtypmod = exprTypmod ((Node * ) phv -> phexpr );
205
+ retval -> location = -1 ;
206
+
207
+ return retval ;
208
+ }
209
+
151
210
/*
152
211
* Generate a Param node to replace the given Aggref
153
212
* which is expected to have agglevelsup > 0 (ie, it is not local).
@@ -449,17 +508,19 @@ build_subplan(PlannerInfo *root, Plan *plan, List *rtable, List *rowmarks,
449
508
Node * arg ;
450
509
451
510
/*
452
- * The Var or Aggref has already been adjusted to have the correct
453
- * varlevelsup or agglevelsup. We probably don't even need to
454
- * copy it again, but be safe.
511
+ * The Var, PlaceHolderVar, or Aggref has already been adjusted to
512
+ * have the correct varlevelsup, phlevelsup, or agglevelsup. We
513
+ * probably don't even need to copy it again, but be safe.
455
514
*/
456
515
arg = copyObject (pitem -> item );
457
516
458
517
/*
459
- * If it's an Aggref, its arguments might contain SubLinks, which
460
- * have not yet been processed. Do that now.
518
+ * If it's a PlaceHolderVar or Aggref, its arguments might contain
519
+ * SubLinks, which have not yet been processed (see the comments
520
+ * for SS_replace_correlation_vars). Do that now.
461
521
*/
462
- if (IsA (arg , Aggref ))
522
+ if (IsA (arg , PlaceHolderVar ) ||
523
+ IsA (arg , Aggref ))
463
524
arg = SS_process_sublinks (root , arg , false);
464
525
465
526
splan -> parParam = lappend_int (splan -> parParam , paramid );
@@ -1539,24 +1600,25 @@ convert_EXISTS_to_ANY(PlannerInfo *root, Query *subselect,
1539
1600
/*
1540
1601
* Replace correlation vars (uplevel vars) with Params.
1541
1602
*
1542
- * Uplevel aggregates are replaced, too.
1603
+ * Uplevel PlaceHolderVars and aggregates are replaced, too.
1543
1604
*
1544
1605
* Note: it is critical that this runs immediately after SS_process_sublinks.
1545
- * Since we do not recurse into the arguments of uplevel aggregates, they will
1546
- * get copied to the appropriate subplan args list in the parent query with
1547
- * uplevel vars not replaced by Params, but only adjusted in level (see
1548
- * replace_outer_agg). That's exactly what we want for the vars of the parent
1549
- * level --- but if an aggregate's argument contains any further-up variables,
1550
- * they have to be replaced with Params in their turn. That will happen when
1551
- * the parent level runs SS_replace_correlation_vars. Therefore it must do
1552
- * so after expanding its sublinks to subplans. And we don't want any steps
1553
- * in between, else those steps would never get applied to the aggregate
1554
- * argument expressions, either in the parent or the child level.
1606
+ * Since we do not recurse into the arguments of uplevel PHVs and aggregates,
1607
+ * they will get copied to the appropriate subplan args list in the parent
1608
+ * query with uplevel vars not replaced by Params, but only adjusted in level
1609
+ * (see replace_outer_placeholdervar and replace_outer_agg). That's exactly
1610
+ * what we want for the vars of the parent level --- but if a PHV's or
1611
+ * aggregate's argument contains any further-up variables, they have to be
1612
+ * replaced with Params in their turn. That will happen when the parent level
1613
+ * runs SS_replace_correlation_vars. Therefore it must do so after expanding
1614
+ * its sublinks to subplans. And we don't want any steps in between, else
1615
+ * those steps would never get applied to the argument expressions, either in
1616
+ * the parent or the child level.
1555
1617
*
1556
1618
* Another fairly tricky thing going on here is the handling of SubLinks in
1557
- * the arguments of uplevel aggregates. Those are not touched inside the
1558
- * intermediate query level, either. Instead, SS_process_sublinks recurses
1559
- * on them after copying the Aggref expression into the parent plan level
1619
+ * the arguments of uplevel PHVs/ aggregates. Those are not touched inside the
1620
+ * intermediate query level, either. Instead, SS_process_sublinks recurses on
1621
+ * them after copying the PHV or Aggref expression into the parent plan level
1560
1622
* (this is actually taken care of in build_subplan).
1561
1623
*/
1562
1624
Node *
@@ -1576,6 +1638,12 @@ replace_correlation_vars_mutator(Node *node, PlannerInfo *root)
1576
1638
if (((Var * ) node )-> varlevelsup > 0 )
1577
1639
return (Node * ) replace_outer_var (root , (Var * ) node );
1578
1640
}
1641
+ if (IsA (node , PlaceHolderVar ))
1642
+ {
1643
+ if (((PlaceHolderVar * ) node )-> phlevelsup > 0 )
1644
+ return (Node * ) replace_outer_placeholdervar (root ,
1645
+ (PlaceHolderVar * ) node );
1646
+ }
1579
1647
if (IsA (node , Aggref ))
1580
1648
{
1581
1649
if (((Aggref * ) node )-> agglevelsup > 0 )
@@ -1635,12 +1703,17 @@ process_sublinks_mutator(Node *node, process_sublinks_context *context)
1635
1703
}
1636
1704
1637
1705
/*
1638
- * Don't recurse into the arguments of an outer aggregate here. Any
1639
- * SubLinks in the arguments have to be dealt with at the outer query
1640
- * level; they'll be handled when build_subplan collects the Aggref into
1641
- * the arguments to be passed down to the current subplan.
1706
+ * Don't recurse into the arguments of an outer PHV or aggregate here.
1707
+ * Any SubLinks in the arguments have to be dealt with at the outer query
1708
+ * level; they'll be handled when build_subplan collects the PHV or Aggref
1709
+ * into the arguments to be passed down to the current subplan.
1642
1710
*/
1643
- if (IsA (node , Aggref ))
1711
+ if (IsA (node , PlaceHolderVar ))
1712
+ {
1713
+ if (((PlaceHolderVar * ) node )-> phlevelsup > 0 )
1714
+ return node ;
1715
+ }
1716
+ else if (IsA (node , Aggref ))
1644
1717
{
1645
1718
if (((Aggref * ) node )-> agglevelsup > 0 )
1646
1719
return node ;
0 commit comments