27
27
#include "optimizer/clauses.h"
28
28
#include "optimizer/cost.h"
29
29
#include "optimizer/paths.h"
30
+ #include "optimizer/placeholder.h"
30
31
#include "optimizer/plancat.h"
31
32
#include "optimizer/planmain.h"
32
33
#include "optimizer/predtest.h"
@@ -1886,7 +1887,20 @@ create_nestloop_plan(PlannerInfo *root,
1886
1887
NestLoopParam * nlp = (NestLoopParam * ) lfirst (cell );
1887
1888
1888
1889
next = 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 ))
1890
1904
{
1891
1905
root -> curOuterParams = list_delete_cell (root -> curOuterParams ,
1892
1906
cell , prev );
@@ -2314,11 +2328,12 @@ create_hashjoin_plan(PlannerInfo *root,
2314
2328
2315
2329
/*
2316
2330
* 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
2318
2333
*
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 Vars and 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.
2322
2337
*/
2323
2338
static Node *
2324
2339
replace_nestloop_params (PlannerInfo * root , Node * expr )
@@ -2345,7 +2360,7 @@ replace_nestloop_params_mutator(Node *node, PlannerInfo *root)
2345
2360
if (!bms_is_member (var -> varno , root -> curOuterRels ))
2346
2361
return node ;
2347
2362
/* Create a Param representing the Var */
2348
- param = assign_nestloop_param (root , var );
2363
+ param = assign_nestloop_param_var (root , var );
2349
2364
/* Is this param already listed in root->curOuterParams? */
2350
2365
foreach (lc , root -> curOuterParams )
2351
2366
{
@@ -2365,6 +2380,48 @@ replace_nestloop_params_mutator(Node *node, PlannerInfo *root)
2365
2380
/* And return the replacement Param */
2366
2381
return (Node * ) param ;
2367
2382
}
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
+ }
2368
2425
return expression_tree_mutator (node ,
2369
2426
replace_nestloop_params_mutator ,
2370
2427
(void * ) root );
@@ -2377,7 +2434,7 @@ replace_nestloop_params_mutator(Node *node, PlannerInfo *root)
2377
2434
*
2378
2435
* We have four tasks here:
2379
2436
* * Remove RestrictInfo nodes from the input clauses.
2380
- * * Replace any outer-relation Var nodes with nestloop Params.
2437
+ * * Replace any outer-relation Var or PHV nodes with nestloop Params.
2381
2438
* (XXX eventually, that responsibility should go elsewhere?)
2382
2439
* * Index keys must be represented by Var nodes with varattno set to the
2383
2440
* index's attribute number, not the attribute number in the original rel.
0 commit comments