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"
@@ -1886,7 +1887,20 @@ create_nestloop_plan(PlannerInfo *root,
18861887NestLoopParam * nlp = (NestLoopParam * )lfirst (cell );
18871888
18881889next = lnext (cell );
1889- if (bms_is_member (nlp -> paramval -> varno ,outerrelids ))
1890+ if (IsA (nlp -> paramval ,Var )&&
1891+ bms_is_member (nlp -> paramval -> varno ,outerrelids ))
1892+ {
1893+ root -> curOuterParams = list_delete_cell (root -> curOuterParams ,
1894+ cell ,prev );
1895+ nestParams = lappend (nestParams ,nlp );
1896+ }
1897+ else if (IsA (nlp -> paramval ,PlaceHolderVar )&&
1898+ bms_overlap (((PlaceHolderVar * )nlp -> paramval )-> phrels ,
1899+ outerrelids )&&
1900+ bms_is_subset (find_placeholder_info (root ,
1901+ (PlaceHolderVar * )nlp -> paramval ,
1902+ false)-> ph_eval_at ,
1903+ outerrelids ))
18901904{
18911905root -> curOuterParams = list_delete_cell (root -> curOuterParams ,
18921906cell ,prev );
@@ -2314,11 +2328,12 @@ create_hashjoin_plan(PlannerInfo *root,
23142328
23152329/*
23162330 * replace_nestloop_params
2317- * Replace outer-relation Vars in the given expression with nestloop Params
2331+ * Replace outer-relation Vars and PlaceHolderVars in the given expression
2332+ * with nestloop Params
23182333 *
2319- * All Vars belonging to the relation(s) identified by root->curOuterRels
2320- * are replaced by Params, and entries are added to root->curOuterParams if
2321- * not already present.
2334+ * All Varsand PlaceHolderVars belonging to the relation(s) identified by
2335+ *root->curOuterRels are replaced by Params, and entries are added to
2336+ *root->curOuterParams if not already present.
23222337 */
23232338static Node *
23242339replace_nestloop_params (PlannerInfo * root ,Node * expr )
@@ -2345,7 +2360,7 @@ replace_nestloop_params_mutator(Node *node, PlannerInfo *root)
23452360if (!bms_is_member (var -> varno ,root -> curOuterRels ))
23462361return node ;
23472362/* Create a Param representing the Var */
2348- param = assign_nestloop_param (root ,var );
2363+ param = assign_nestloop_param_var (root ,var );
23492364/* Is this param already listed in root->curOuterParams? */
23502365foreach (lc ,root -> curOuterParams )
23512366{
@@ -2365,6 +2380,48 @@ replace_nestloop_params_mutator(Node *node, PlannerInfo *root)
23652380/* And return the replacement Param */
23662381return (Node * )param ;
23672382}
2383+ if (IsA (node ,PlaceHolderVar ))
2384+ {
2385+ PlaceHolderVar * phv = (PlaceHolderVar * )node ;
2386+ Param * param ;
2387+ NestLoopParam * nlp ;
2388+ ListCell * lc ;
2389+
2390+ /* Upper-level PlaceHolderVars should be long gone at this point */
2391+ Assert (phv -> phlevelsup == 0 );
2392+
2393+ /*
2394+ * If not to be replaced, just return the PlaceHolderVar unmodified.
2395+ * We use bms_overlap as a cheap/quick test to see if the PHV might
2396+ * be evaluated in the outer rels, and then grab its PlaceHolderInfo
2397+ * to tell for sure.
2398+ */
2399+ if (!bms_overlap (phv -> phrels ,root -> curOuterRels ))
2400+ return node ;
2401+ if (!bms_is_subset (find_placeholder_info (root ,phv , false)-> ph_eval_at ,
2402+ root -> curOuterRels ))
2403+ return node ;
2404+ /* Create a Param representing the PlaceHolderVar */
2405+ param = assign_nestloop_param_placeholdervar (root ,phv );
2406+ /* Is this param already listed in root->curOuterParams? */
2407+ foreach (lc ,root -> curOuterParams )
2408+ {
2409+ nlp = (NestLoopParam * )lfirst (lc );
2410+ if (nlp -> paramno == param -> paramid )
2411+ {
2412+ Assert (equal (phv ,nlp -> paramval ));
2413+ /* Present, so we can just return the Param */
2414+ return (Node * )param ;
2415+ }
2416+ }
2417+ /* No, so add it */
2418+ nlp = makeNode (NestLoopParam );
2419+ nlp -> paramno = param -> paramid ;
2420+ nlp -> paramval = (Var * )phv ;
2421+ root -> curOuterParams = lappend (root -> curOuterParams ,nlp );
2422+ /* And return the replacement Param */
2423+ return (Node * )param ;
2424+ }
23682425return expression_tree_mutator (node ,
23692426replace_nestloop_params_mutator ,
23702427 (void * )root );
@@ -2377,7 +2434,7 @@ replace_nestloop_params_mutator(Node *node, PlannerInfo *root)
23772434 *
23782435 * We have four tasks here:
23792436 ** Remove RestrictInfo nodes from the input clauses.
2380- ** Replace any outer-relation Var nodes with nestloop Params.
2437+ ** Replace any outer-relation Varor PHV nodes with nestloop Params.
23812438 * (XXX eventually, that responsibility should go elsewhere?)
23822439 ** Index keys must be represented by Var nodes with varattno set to the
23832440 * index's attribute number, not the attribute number in the original rel.