@@ -191,25 +191,22 @@ assign_nestloop_param_var(PlannerInfo *root, Var *var)
191
191
}
192
192
193
193
/*
194
- * Generate a Param node to replace the given PlaceHolderVar, which will be
195
- * supplied from an upper NestLoop join node .
194
+ * Select a PARAM_EXEC number to identify the given PlaceHolderVar.
195
+ * If the PlaceHolderVar already has a param slot, return that one .
196
196
*
197
- * This is just like assign_nestloop_param_var , except for PlaceHolderVars.
197
+ * This is just like assign_param_for_var , except for PlaceHolderVars.
198
198
*/
199
- Param *
200
- assign_nestloop_param_placeholdervar (PlannerInfo * root , PlaceHolderVar * phv )
199
+ static int
200
+ assign_param_for_placeholdervar (PlannerInfo * root , PlaceHolderVar * phv )
201
201
{
202
- Param * retval ;
203
202
ListCell * ppl ;
204
203
PlannerParamItem * pitem ;
205
204
Index abslevel ;
206
205
int i ;
207
206
208
- Assert (phv -> phlevelsup == 0 );
209
- abslevel = root -> query_level ;
207
+ abslevel = root -> query_level - phv -> phlevelsup ;
210
208
211
209
/* If there's already a paramlist entry for this same PHV, just use it */
212
- /* We assume comparing the PHIDs is sufficient */
213
210
i = 0 ;
214
211
foreach (ppl , root -> glob -> paramlist )
215
212
{
@@ -218,25 +215,77 @@ assign_nestloop_param_placeholdervar(PlannerInfo *root, PlaceHolderVar *phv)
218
215
{
219
216
PlaceHolderVar * pphv = (PlaceHolderVar * ) pitem -> item ;
220
217
218
+ /* We assume comparing the PHIDs is sufficient */
221
219
if (pphv -> phid == phv -> phid )
222
- break ;
220
+ return i ;
223
221
}
224
222
i ++ ;
225
223
}
226
224
227
- if (ppl == NULL )
225
+ /* Nope, so make a new one */
226
+ phv = (PlaceHolderVar * ) copyObject (phv );
227
+ if (phv -> phlevelsup != 0 )
228
228
{
229
- /* Nope, so make a new one */
230
- phv = (PlaceHolderVar * ) copyObject (phv );
229
+ IncrementVarSublevelsUp ((Node * ) phv , - ((int ) phv -> phlevelsup ), 0 );
230
+ Assert (phv -> phlevelsup == 0 );
231
+ }
231
232
232
- pitem = makeNode (PlannerParamItem );
233
- pitem -> item = (Node * ) phv ;
234
- pitem -> abslevel = abslevel ;
233
+ pitem = makeNode (PlannerParamItem );
234
+ pitem -> item = (Node * ) phv ;
235
+ pitem -> abslevel = abslevel ;
235
236
236
- root -> glob -> paramlist = lappend (root -> glob -> paramlist , pitem );
237
+ root -> glob -> paramlist = lappend (root -> glob -> paramlist , pitem );
237
238
238
- /* i is already the correct list index for the new item */
239
- }
239
+ /* i is already the correct list index for the new item */
240
+ return i ;
241
+ }
242
+
243
+ /*
244
+ * Generate a Param node to replace the given PlaceHolderVar,
245
+ * which is expected to have phlevelsup > 0 (ie, it is not local).
246
+ *
247
+ * This is just like replace_outer_var, except for PlaceHolderVars.
248
+ */
249
+ static Param *
250
+ replace_outer_placeholdervar (PlannerInfo * root , PlaceHolderVar * phv )
251
+ {
252
+ Param * retval ;
253
+ int i ;
254
+
255
+ Assert (phv -> phlevelsup > 0 && phv -> phlevelsup < root -> query_level );
256
+
257
+ /*
258
+ * Find the PlaceHolderVar in root->glob->paramlist, or add it if not
259
+ * present.
260
+ */
261
+ i = assign_param_for_placeholdervar (root , phv );
262
+
263
+ retval = makeNode (Param );
264
+ retval -> paramkind = PARAM_EXEC ;
265
+ retval -> paramid = i ;
266
+ retval -> paramtype = exprType ((Node * ) phv -> phexpr );
267
+ retval -> paramtypmod = exprTypmod ((Node * ) phv -> phexpr );
268
+ retval -> paramcollid = exprCollation ((Node * ) phv -> phexpr );
269
+ retval -> location = -1 ;
270
+
271
+ return retval ;
272
+ }
273
+
274
+ /*
275
+ * Generate a Param node to replace the given PlaceHolderVar, which will be
276
+ * supplied from an upper NestLoop join node.
277
+ *
278
+ * This is just like assign_nestloop_param_var, except for PlaceHolderVars.
279
+ */
280
+ Param *
281
+ assign_nestloop_param_placeholdervar (PlannerInfo * root , PlaceHolderVar * phv )
282
+ {
283
+ Param * retval ;
284
+ int i ;
285
+
286
+ Assert (phv -> phlevelsup == 0 );
287
+
288
+ i = assign_param_for_placeholdervar (root , phv );
240
289
241
290
retval = makeNode (Param );
242
291
retval -> paramkind = PARAM_EXEC ;
@@ -555,17 +604,19 @@ build_subplan(PlannerInfo *root, Plan *plan, PlannerInfo *subroot,
555
604
Node * arg ;
556
605
557
606
/*
558
- * The Var or Aggref has already been adjusted to have the correct
559
- * varlevelsup or agglevelsup. We probably don't even need to
560
- * copy it again, but be safe.
607
+ * The Var, PlaceHolderVar, or Aggref has already been adjusted to
608
+ * have the correct varlevelsup, phlevelsup, or agglevelsup. We
609
+ * probably don't even need to copy it again, but be safe.
561
610
*/
562
611
arg = copyObject (pitem -> item );
563
612
564
613
/*
565
- * If it's an Aggref, its arguments might contain SubLinks, which
566
- * have not yet been processed. Do that now.
614
+ * If it's a PlaceHolderVar or Aggref, its arguments might contain
615
+ * SubLinks, which have not yet been processed (see the comments
616
+ * for SS_replace_correlation_vars). Do that now.
567
617
*/
568
- if (IsA (arg , Aggref ))
618
+ if (IsA (arg , PlaceHolderVar ) ||
619
+ IsA (arg , Aggref ))
569
620
arg = SS_process_sublinks (root , arg , false);
570
621
571
622
splan -> parParam = lappend_int (splan -> parParam , paramid );
@@ -1668,24 +1719,25 @@ convert_EXISTS_to_ANY(PlannerInfo *root, Query *subselect,
1668
1719
/*
1669
1720
* Replace correlation vars (uplevel vars) with Params.
1670
1721
*
1671
- * Uplevel aggregates are replaced, too.
1722
+ * Uplevel PlaceHolderVars and aggregates are replaced, too.
1672
1723
*
1673
1724
* Note: it is critical that this runs immediately after SS_process_sublinks.
1674
- * Since we do not recurse into the arguments of uplevel aggregates, they will
1675
- * get copied to the appropriate subplan args list in the parent query with
1676
- * uplevel vars not replaced by Params, but only adjusted in level (see
1677
- * replace_outer_agg). That's exactly what we want for the vars of the parent
1678
- * level --- but if an aggregate's argument contains any further-up variables,
1679
- * they have to be replaced with Params in their turn. That will happen when
1680
- * the parent level runs SS_replace_correlation_vars. Therefore it must do
1681
- * so after expanding its sublinks to subplans. And we don't want any steps
1682
- * in between, else those steps would never get applied to the aggregate
1683
- * argument expressions, either in the parent or the child level.
1725
+ * Since we do not recurse into the arguments of uplevel PHVs and aggregates,
1726
+ * they will get copied to the appropriate subplan args list in the parent
1727
+ * query with uplevel vars not replaced by Params, but only adjusted in level
1728
+ * (see replace_outer_placeholdervar and replace_outer_agg). That's exactly
1729
+ * what we want for the vars of the parent level --- but if a PHV's or
1730
+ * aggregate's argument contains any further-up variables, they have to be
1731
+ * replaced with Params in their turn. That will happen when the parent level
1732
+ * runs SS_replace_correlation_vars. Therefore it must do so after expanding
1733
+ * its sublinks to subplans. And we don't want any steps in between, else
1734
+ * those steps would never get applied to the argument expressions, either in
1735
+ * the parent or the child level.
1684
1736
*
1685
1737
* Another fairly tricky thing going on here is the handling of SubLinks in
1686
- * the arguments of uplevel aggregates. Those are not touched inside the
1687
- * intermediate query level, either. Instead, SS_process_sublinks recurses
1688
- * on them after copying the Aggref expression into the parent plan level
1738
+ * the arguments of uplevel PHVs/ aggregates. Those are not touched inside the
1739
+ * intermediate query level, either. Instead, SS_process_sublinks recurses on
1740
+ * them after copying the PHV or Aggref expression into the parent plan level
1689
1741
* (this is actually taken care of in build_subplan).
1690
1742
*/
1691
1743
Node *
@@ -1705,6 +1757,12 @@ replace_correlation_vars_mutator(Node *node, PlannerInfo *root)
1705
1757
if (((Var * ) node )-> varlevelsup > 0 )
1706
1758
return (Node * ) replace_outer_var (root , (Var * ) node );
1707
1759
}
1760
+ if (IsA (node , PlaceHolderVar ))
1761
+ {
1762
+ if (((PlaceHolderVar * ) node )-> phlevelsup > 0 )
1763
+ return (Node * ) replace_outer_placeholdervar (root ,
1764
+ (PlaceHolderVar * ) node );
1765
+ }
1708
1766
if (IsA (node , Aggref ))
1709
1767
{
1710
1768
if (((Aggref * ) node )-> agglevelsup > 0 )
@@ -1764,12 +1822,17 @@ process_sublinks_mutator(Node *node, process_sublinks_context *context)
1764
1822
}
1765
1823
1766
1824
/*
1767
- * Don't recurse into the arguments of an outer aggregate here. Any
1768
- * SubLinks in the arguments have to be dealt with at the outer query
1769
- * level; they'll be handled when build_subplan collects the Aggref into
1770
- * the arguments to be passed down to the current subplan.
1825
+ * Don't recurse into the arguments of an outer PHV or aggregate here.
1826
+ * Any SubLinks in the arguments have to be dealt with at the outer query
1827
+ * level; they'll be handled when build_subplan collects the PHV or Aggref
1828
+ * into the arguments to be passed down to the current subplan.
1771
1829
*/
1772
- if (IsA (node , Aggref ))
1830
+ if (IsA (node , PlaceHolderVar ))
1831
+ {
1832
+ if (((PlaceHolderVar * ) node )-> phlevelsup > 0 )
1833
+ return node ;
1834
+ }
1835
+ else if (IsA (node , Aggref ))
1773
1836
{
1774
1837
if (((Aggref * ) node )-> agglevelsup > 0 )
1775
1838
return node ;
0 commit comments