@@ -193,25 +193,22 @@ assign_nestloop_param_var(PlannerInfo *root, Var *var)
193
193
}
194
194
195
195
/*
196
- * Generate a Param node to replace the given PlaceHolderVar, which will be
197
- * supplied from an upper NestLoop join node .
196
+ * Select a PARAM_EXEC number to identify the given PlaceHolderVar.
197
+ * If the PlaceHolderVar already has a param slot, return that one .
198
198
*
199
- * This is just like assign_nestloop_param_var , except for PlaceHolderVars.
199
+ * This is just like assign_param_for_var , except for PlaceHolderVars.
200
200
*/
201
- Param *
202
- assign_nestloop_param_placeholdervar (PlannerInfo * root , PlaceHolderVar * phv )
201
+ static int
202
+ assign_param_for_placeholdervar (PlannerInfo * root , PlaceHolderVar * phv )
203
203
{
204
- Param * retval ;
205
204
ListCell * ppl ;
206
205
PlannerParamItem * pitem ;
207
206
Index abslevel ;
208
207
int i ;
209
208
210
- Assert (phv -> phlevelsup == 0 );
211
- abslevel = root -> query_level ;
209
+ abslevel = root -> query_level - phv -> phlevelsup ;
212
210
213
211
/* If there's already a paramlist entry for this same PHV, just use it */
214
- /* We assume comparing the PHIDs is sufficient */
215
212
i = 0 ;
216
213
foreach (ppl , root -> glob -> paramlist )
217
214
{
@@ -220,25 +217,77 @@ assign_nestloop_param_placeholdervar(PlannerInfo *root, PlaceHolderVar *phv)
220
217
{
221
218
PlaceHolderVar * pphv = (PlaceHolderVar * ) pitem -> item ;
222
219
220
+ /* We assume comparing the PHIDs is sufficient */
223
221
if (pphv -> phid == phv -> phid )
224
- break ;
222
+ return i ;
225
223
}
226
224
i ++ ;
227
225
}
228
226
229
- if (ppl == NULL )
227
+ /* Nope, so make a new one */
228
+ phv = (PlaceHolderVar * ) copyObject (phv );
229
+ if (phv -> phlevelsup != 0 )
230
230
{
231
- /* Nope, so make a new one */
232
- phv = (PlaceHolderVar * ) copyObject (phv );
231
+ IncrementVarSublevelsUp ((Node * ) phv , - ((int ) phv -> phlevelsup ), 0 );
232
+ Assert (phv -> phlevelsup == 0 );
233
+ }
233
234
234
- pitem = makeNode (PlannerParamItem );
235
- pitem -> item = (Node * ) phv ;
236
- pitem -> abslevel = abslevel ;
235
+ pitem = makeNode (PlannerParamItem );
236
+ pitem -> item = (Node * ) phv ;
237
+ pitem -> abslevel = abslevel ;
237
238
238
- root -> glob -> paramlist = lappend (root -> glob -> paramlist , pitem );
239
+ root -> glob -> paramlist = lappend (root -> glob -> paramlist , pitem );
239
240
240
- /* i is already the correct list index for the new item */
241
- }
241
+ /* i is already the correct list index for the new item */
242
+ return i ;
243
+ }
244
+
245
+ /*
246
+ * Generate a Param node to replace the given PlaceHolderVar,
247
+ * which is expected to have phlevelsup > 0 (ie, it is not local).
248
+ *
249
+ * This is just like replace_outer_var, except for PlaceHolderVars.
250
+ */
251
+ static Param *
252
+ replace_outer_placeholdervar (PlannerInfo * root , PlaceHolderVar * phv )
253
+ {
254
+ Param * retval ;
255
+ int i ;
256
+
257
+ Assert (phv -> phlevelsup > 0 && phv -> phlevelsup < root -> query_level );
258
+
259
+ /*
260
+ * Find the PlaceHolderVar in root->glob->paramlist, or add it if not
261
+ * present.
262
+ */
263
+ i = assign_param_for_placeholdervar (root , phv );
264
+
265
+ retval = makeNode (Param );
266
+ retval -> paramkind = PARAM_EXEC ;
267
+ retval -> paramid = i ;
268
+ retval -> paramtype = exprType ((Node * ) phv -> phexpr );
269
+ retval -> paramtypmod = exprTypmod ((Node * ) phv -> phexpr );
270
+ retval -> paramcollid = exprCollation ((Node * ) phv -> phexpr );
271
+ retval -> location = -1 ;
272
+
273
+ return retval ;
274
+ }
275
+
276
+ /*
277
+ * Generate a Param node to replace the given PlaceHolderVar, which will be
278
+ * supplied from an upper NestLoop join node.
279
+ *
280
+ * This is just like assign_nestloop_param_var, except for PlaceHolderVars.
281
+ */
282
+ Param *
283
+ assign_nestloop_param_placeholdervar (PlannerInfo * root , PlaceHolderVar * phv )
284
+ {
285
+ Param * retval ;
286
+ int i ;
287
+
288
+ Assert (phv -> phlevelsup == 0 );
289
+
290
+ i = assign_param_for_placeholdervar (root , phv );
242
291
243
292
retval = makeNode (Param );
244
293
retval -> paramkind = PARAM_EXEC ;
@@ -560,17 +609,19 @@ build_subplan(PlannerInfo *root, Plan *plan, List *rtable, List *rowmarks,
560
609
Node * arg ;
561
610
562
611
/*
563
- * The Var or Aggref has already been adjusted to have the correct
564
- * varlevelsup or agglevelsup. We probably don't even need to
565
- * copy it again, but be safe.
612
+ * The Var, PlaceHolderVar, or Aggref has already been adjusted to
613
+ * have the correct varlevelsup, phlevelsup, or agglevelsup. We
614
+ * probably don't even need to copy it again, but be safe.
566
615
*/
567
616
arg = copyObject (pitem -> item );
568
617
569
618
/*
570
- * If it's an Aggref, its arguments might contain SubLinks, which
571
- * have not yet been processed. Do that now.
619
+ * If it's a PlaceHolderVar or Aggref, its arguments might contain
620
+ * SubLinks, which have not yet been processed (see the comments
621
+ * for SS_replace_correlation_vars). Do that now.
572
622
*/
573
- if (IsA (arg , Aggref ))
623
+ if (IsA (arg , PlaceHolderVar ) ||
624
+ IsA (arg , Aggref ))
574
625
arg = SS_process_sublinks (root , arg , false);
575
626
576
627
splan -> parParam = lappend_int (splan -> parParam , paramid );
@@ -1678,24 +1729,25 @@ convert_EXISTS_to_ANY(PlannerInfo *root, Query *subselect,
1678
1729
/*
1679
1730
* Replace correlation vars (uplevel vars) with Params.
1680
1731
*
1681
- * Uplevel aggregates are replaced, too.
1732
+ * Uplevel PlaceHolderVars and aggregates are replaced, too.
1682
1733
*
1683
1734
* Note: it is critical that this runs immediately after SS_process_sublinks.
1684
- * Since we do not recurse into the arguments of uplevel aggregates, they will
1685
- * get copied to the appropriate subplan args list in the parent query with
1686
- * uplevel vars not replaced by Params, but only adjusted in level (see
1687
- * replace_outer_agg). That's exactly what we want for the vars of the parent
1688
- * level --- but if an aggregate's argument contains any further-up variables,
1689
- * they have to be replaced with Params in their turn. That will happen when
1690
- * the parent level runs SS_replace_correlation_vars. Therefore it must do
1691
- * so after expanding its sublinks to subplans. And we don't want any steps
1692
- * in between, else those steps would never get applied to the aggregate
1693
- * argument expressions, either in the parent or the child level.
1735
+ * Since we do not recurse into the arguments of uplevel PHVs and aggregates,
1736
+ * they will get copied to the appropriate subplan args list in the parent
1737
+ * query with uplevel vars not replaced by Params, but only adjusted in level
1738
+ * (see replace_outer_placeholdervar and replace_outer_agg). That's exactly
1739
+ * what we want for the vars of the parent level --- but if a PHV's or
1740
+ * aggregate's argument contains any further-up variables, they have to be
1741
+ * replaced with Params in their turn. That will happen when the parent level
1742
+ * runs SS_replace_correlation_vars. Therefore it must do so after expanding
1743
+ * its sublinks to subplans. And we don't want any steps in between, else
1744
+ * those steps would never get applied to the argument expressions, either in
1745
+ * the parent or the child level.
1694
1746
*
1695
1747
* Another fairly tricky thing going on here is the handling of SubLinks in
1696
- * the arguments of uplevel aggregates. Those are not touched inside the
1697
- * intermediate query level, either. Instead, SS_process_sublinks recurses
1698
- * on them after copying the Aggref expression into the parent plan level
1748
+ * the arguments of uplevel PHVs/ aggregates. Those are not touched inside the
1749
+ * intermediate query level, either. Instead, SS_process_sublinks recurses on
1750
+ * them after copying the PHV or Aggref expression into the parent plan level
1699
1751
* (this is actually taken care of in build_subplan).
1700
1752
*/
1701
1753
Node *
@@ -1715,6 +1767,12 @@ replace_correlation_vars_mutator(Node *node, PlannerInfo *root)
1715
1767
if (((Var * ) node )-> varlevelsup > 0 )
1716
1768
return (Node * ) replace_outer_var (root , (Var * ) node );
1717
1769
}
1770
+ if (IsA (node , PlaceHolderVar ))
1771
+ {
1772
+ if (((PlaceHolderVar * ) node )-> phlevelsup > 0 )
1773
+ return (Node * ) replace_outer_placeholdervar (root ,
1774
+ (PlaceHolderVar * ) node );
1775
+ }
1718
1776
if (IsA (node , Aggref ))
1719
1777
{
1720
1778
if (((Aggref * ) node )-> agglevelsup > 0 )
@@ -1774,12 +1832,17 @@ process_sublinks_mutator(Node *node, process_sublinks_context *context)
1774
1832
}
1775
1833
1776
1834
/*
1777
- * Don't recurse into the arguments of an outer aggregate here. Any
1778
- * SubLinks in the arguments have to be dealt with at the outer query
1779
- * level; they'll be handled when build_subplan collects the Aggref into
1780
- * the arguments to be passed down to the current subplan.
1835
+ * Don't recurse into the arguments of an outer PHV or aggregate here.
1836
+ * Any SubLinks in the arguments have to be dealt with at the outer query
1837
+ * level; they'll be handled when build_subplan collects the PHV or Aggref
1838
+ * into the arguments to be passed down to the current subplan.
1781
1839
*/
1782
- if (IsA (node , Aggref ))
1840
+ if (IsA (node , PlaceHolderVar ))
1841
+ {
1842
+ if (((PlaceHolderVar * ) node )-> phlevelsup > 0 )
1843
+ return node ;
1844
+ }
1845
+ else if (IsA (node , Aggref ))
1783
1846
{
1784
1847
if (((Aggref * ) node )-> agglevelsup > 0 )
1785
1848
return node ;
0 commit comments