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,
19261927 NestLoopParam * nlp = (NestLoopParam * ) lfirst (cell );
19271928
19281929 next = 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 {
19311945 root -> curOuterParams = list_delete_cell (root -> curOuterParams ,
19321946 cell , 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 Vars and 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)
23852400 if (!bms_is_member (var -> varno , root -> curOuterRels ))
23862401 return 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? */
23902405 foreach (lc , root -> curOuterParams )
23912406 {
@@ -2405,6 +2420,48 @@ replace_nestloop_params_mutator(Node *node, PlannerInfo *root)
24052420 /* And return the replacement Param */
24062421 return (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+ }
24082465 return expression_tree_mutator (node ,
24092466 replace_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 Var or 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.
0 commit comments