2727#include "optimizer/clauses.h"
2828#include "optimizer/cost.h"
2929#include "optimizer/paths.h"
30+ #include "optimizer/placeholder.h"
3031#include "optimizer/plancat.h"
3132#include "optimizer/planmain.h"
3233#include "optimizer/predtest.h"
@@ -1926,7 +1927,20 @@ create_nestloop_plan(PlannerInfo *root,
19261927NestLoopParam * nlp = (NestLoopParam * )lfirst (cell );
19271928
19281929next = lnext (cell );
1929- if (bms_is_member (nlp -> paramval -> varno ,outerrelids ))
1930+ if (IsA (nlp -> paramval ,Var )&&
1931+ bms_is_member (nlp -> paramval -> varno ,outerrelids ))
1932+ {
1933+ root -> curOuterParams = list_delete_cell (root -> curOuterParams ,
1934+ cell ,prev );
1935+ nestParams = lappend (nestParams ,nlp );
1936+ }
1937+ else if (IsA (nlp -> paramval ,PlaceHolderVar )&&
1938+ bms_overlap (((PlaceHolderVar * )nlp -> paramval )-> phrels ,
1939+ outerrelids )&&
1940+ bms_is_subset (find_placeholder_info (root ,
1941+ (PlaceHolderVar * )nlp -> paramval ,
1942+ false)-> ph_eval_at ,
1943+ outerrelids ))
19301944{
19311945root -> curOuterParams = list_delete_cell (root -> curOuterParams ,
19321946cell ,prev );
@@ -2354,11 +2368,12 @@ create_hashjoin_plan(PlannerInfo *root,
23542368
23552369/*
23562370 * replace_nestloop_params
2357- * Replace outer-relation Vars in the given expression with nestloop Params
2371+ * Replace outer-relation Vars and PlaceHolderVars in the given expression
2372+ * with nestloop Params
23582373 *
2359- * All Vars belonging to the relation(s) identified by root->curOuterRels
2360- * are replaced by Params, and entries are added to root->curOuterParams if
2361- * not already present.
2374+ * All Varsand PlaceHolderVars belonging to the relation(s) identified by
2375+ *root->curOuterRels are replaced by Params, and entries are added to
2376+ *root->curOuterParams if not already present.
23622377 */
23632378static Node *
23642379replace_nestloop_params (PlannerInfo * root ,Node * expr )
@@ -2385,7 +2400,7 @@ replace_nestloop_params_mutator(Node *node, PlannerInfo *root)
23852400if (!bms_is_member (var -> varno ,root -> curOuterRels ))
23862401return node ;
23872402/* Create a Param representing the Var */
2388- param = assign_nestloop_param (root ,var );
2403+ param = assign_nestloop_param_var (root ,var );
23892404/* Is this param already listed in root->curOuterParams? */
23902405foreach (lc ,root -> curOuterParams )
23912406{
@@ -2405,6 +2420,48 @@ replace_nestloop_params_mutator(Node *node, PlannerInfo *root)
24052420/* And return the replacement Param */
24062421return (Node * )param ;
24072422}
2423+ if (IsA (node ,PlaceHolderVar ))
2424+ {
2425+ PlaceHolderVar * phv = (PlaceHolderVar * )node ;
2426+ Param * param ;
2427+ NestLoopParam * nlp ;
2428+ ListCell * lc ;
2429+
2430+ /* Upper-level PlaceHolderVars should be long gone at this point */
2431+ Assert (phv -> phlevelsup == 0 );
2432+
2433+ /*
2434+ * If not to be replaced, just return the PlaceHolderVar unmodified.
2435+ * We use bms_overlap as a cheap/quick test to see if the PHV might
2436+ * be evaluated in the outer rels, and then grab its PlaceHolderInfo
2437+ * to tell for sure.
2438+ */
2439+ if (!bms_overlap (phv -> phrels ,root -> curOuterRels ))
2440+ return node ;
2441+ if (!bms_is_subset (find_placeholder_info (root ,phv , false)-> ph_eval_at ,
2442+ root -> curOuterRels ))
2443+ return node ;
2444+ /* Create a Param representing the PlaceHolderVar */
2445+ param = assign_nestloop_param_placeholdervar (root ,phv );
2446+ /* Is this param already listed in root->curOuterParams? */
2447+ foreach (lc ,root -> curOuterParams )
2448+ {
2449+ nlp = (NestLoopParam * )lfirst (lc );
2450+ if (nlp -> paramno == param -> paramid )
2451+ {
2452+ Assert (equal (phv ,nlp -> paramval ));
2453+ /* Present, so we can just return the Param */
2454+ return (Node * )param ;
2455+ }
2456+ }
2457+ /* No, so add it */
2458+ nlp = makeNode (NestLoopParam );
2459+ nlp -> paramno = param -> paramid ;
2460+ nlp -> paramval = (Var * )phv ;
2461+ root -> curOuterParams = lappend (root -> curOuterParams ,nlp );
2462+ /* And return the replacement Param */
2463+ return (Node * )param ;
2464+ }
24082465return expression_tree_mutator (node ,
24092466replace_nestloop_params_mutator ,
24102467 (void * )root );
@@ -2417,7 +2474,7 @@ replace_nestloop_params_mutator(Node *node, PlannerInfo *root)
24172474 *
24182475 * We have four tasks here:
24192476 ** Remove RestrictInfo nodes from the input clauses.
2420- ** Replace any outer-relation Var nodes with nestloop Params.
2477+ ** Replace any outer-relation Varor PHV nodes with nestloop Params.
24212478 * (XXX eventually, that responsibility should go elsewhere?)
24222479 ** Index keys must be represented by Var nodes with varattno set to the
24232480 * index's attribute number, not the attribute number in the original rel.